From beb6a26cead252839c0ab7e5efdb4be01266d8f9 Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Wed, 18 Mar 2020 18:31:08 -0700 Subject: [PATCH] [Arm64] Implement Store Hardware Intrinsic (#33535) --- src/coreclr/src/jit/codegenarm64.cpp | 12 +- src/coreclr/src/jit/emitarm64.cpp | 16 +- src/coreclr/src/jit/emitfmtsarm64.h | 4 +- src/coreclr/src/jit/hwintrinsic.cpp | 5 +- src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp | 4 + src/coreclr/src/jit/hwintrinsiclistarm64.h | 1 + src/coreclr/src/jit/hwintrinsiclistxarch.h | 36 +- src/coreclr/src/jit/instrsarm64.h | 26 ++ .../Arm/AdvSimd/AdvSimd_r.csproj | 20 + .../Arm/AdvSimd/AdvSimd_ro.csproj | 20 + .../Arm/AdvSimd/Program.AdvSimd.cs | 20 + .../Arm/AdvSimd/Store.Vector128.Byte.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector128.Double.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector128.Int16.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector128.Int32.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector128.Int64.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector128.SByte.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector128.Single.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector128.UInt16.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector128.UInt32.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector128.UInt64.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector64.Byte.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector64.Double.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector64.Int16.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector64.Int32.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector64.Int64.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector64.SByte.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector64.Single.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector64.UInt16.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector64.UInt32.cs | 459 +++++++++++++++++++++ .../Arm/AdvSimd/Store.Vector64.UInt64.cs | 459 +++++++++++++++++++++ .../Arm/Shared/GenerateTests.csx | 20 + .../Arm/Shared/StoreUnOpTest.template | 459 +++++++++++++++++++++ .../Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs | 164 +++++++- .../src/System/Runtime/Intrinsics/Arm/AdvSimd.cs | 164 +++++++- .../ref/System.Runtime.Intrinsics.Experimental.cs | 20 + 36 files changed, 10110 insertions(+), 61 deletions(-) create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Byte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Double.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Int16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Int32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Int64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.SByte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Single.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.UInt16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.UInt32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.UInt64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Byte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Double.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Int16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Int32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Int64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.SByte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Single.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.UInt16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.UInt32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.UInt64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/StoreUnOpTest.template diff --git a/src/coreclr/src/jit/codegenarm64.cpp b/src/coreclr/src/jit/codegenarm64.cpp index 4970dbd..675fca4 100644 --- a/src/coreclr/src/jit/codegenarm64.cpp +++ b/src/coreclr/src/jit/codegenarm64.cpp @@ -5230,7 +5230,7 @@ void CodeGen::genArm64EmitterUnitTests() #ifdef ALL_ARM64_EMITTER_UNIT_TESTS // - // Loads to /Stores from one, two, three, or four SIMD&FP registers + // Loads to and Stores from one, two, three, or four SIMD&FP registers // genDefineTempLabel(genCreateTempLabel()); @@ -5413,7 +5413,7 @@ void CodeGen::genArm64EmitterUnitTests() #ifdef ALL_ARM64_EMITTER_UNIT_TESTS // - // Loads to /Stores from one, two, three, or four SIMD&FP registers + // Loads to and Stores from one, two, three, or four SIMD&FP registers // genDefineTempLabel(genCreateTempLabel()); @@ -5596,7 +5596,7 @@ void CodeGen::genArm64EmitterUnitTests() #ifdef ALL_ARM64_EMITTER_UNIT_TESTS // - // Loads to /Stores from one, two, three, or four SIMD&FP registers + // Loads to and Stores from one, two, three, or four SIMD&FP registers // genDefineTempLabel(genCreateTempLabel()); @@ -5779,7 +5779,7 @@ void CodeGen::genArm64EmitterUnitTests() #ifdef ALL_ARM64_EMITTER_UNIT_TESTS // - // Loads to /Stores from one, two, three, or four SIMD&FP registers + // Loads to and Stores from one, two, three, or four SIMD&FP registers // genDefineTempLabel(genCreateTempLabel()); @@ -5836,7 +5836,7 @@ void CodeGen::genArm64EmitterUnitTests() #ifdef ALL_ARM64_EMITTER_UNIT_TESTS // - // Loads to /Stores from one, two, three, or four SIMD&FP registers + // Loads to and Stores from one, two, three, or four SIMD&FP registers // genDefineTempLabel(genCreateTempLabel()); @@ -5893,7 +5893,7 @@ void CodeGen::genArm64EmitterUnitTests() #ifdef ALL_ARM64_EMITTER_UNIT_TESTS // - // Loads to /Stores from one, two, three, or four SIMD&FP registers + // Loads to and Stores from one, two, three, or four SIMD&FP registers // genDefineTempLabel(genCreateTempLabel()); diff --git a/src/coreclr/src/jit/emitarm64.cpp b/src/coreclr/src/jit/emitarm64.cpp index e31a9ab..2ce9ed6 100644 --- a/src/coreclr/src/jit/emitarm64.cpp +++ b/src/coreclr/src/jit/emitarm64.cpp @@ -229,8 +229,8 @@ void emitter::emitInsSanityCheck(instrDesc* id) case IF_LS_2D: // LS_2D .Q.............. ....ssnnnnnttttt Vt Rn case IF_LS_2E: // LS_2E .Q.............. ....ssnnnnnttttt Vt Rn - case IF_LS_2F: // LS_2F .Q.............. ...Sssnnnnnttttt Vt[] Rn - case IF_LS_2G: // LS_2G .Q.............. ...Sssnnnnnttttt Vt[] Rn + case IF_LS_2F: // LS_2F .Q.............. xx.Sssnnnnnttttt Vt[] Rn + case IF_LS_2G: // LS_2G .Q.............. xx.Sssnnnnnttttt Vt[] Rn assert(isVectorRegister(id->idReg1())); assert(isIntegerRegister(id->idReg2())); // SP if (insOptsAnyArrangement(id->idInsOpt())) @@ -959,8 +959,8 @@ bool emitter::emitInsMayWriteToGCReg(instrDesc* id) case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiP.nnnnnttttt Rt Rn imm(-256..+255) pre/post inc case IF_LS_2D: // LS_2D .Q.............. ....ssnnnnnttttt Vt Rn case IF_LS_2E: // LS_2E .Q.............. ....ssnnnnnttttt Vt Rn - case IF_LS_2F: // LS_2F .Q.............. ...Sssnnnnnttttt Vt[] Rn - case IF_LS_2G: // LS_2G .Q.............. ...Sssnnnnnttttt Vt[] Rn + case IF_LS_2F: // LS_2F .Q.............. xx.Sssnnnnnttttt Vt[] Rn + case IF_LS_2G: // LS_2G .Q.............. xx.Sssnnnnnttttt Vt[] Rn case IF_LS_3A: // LS_3A .X.......X.mmmmm xxxS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {} case IF_LS_3B: // LS_3B X............... .aaaaannnnnttttt Rt Ra Rn case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnttttt Rt Ra Rn imm(im7,sh) @@ -9762,8 +9762,8 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) dst += emitOutput_Instr(dst, code); break; - case IF_LS_2F: // LS_2F .Q.............. ...Sssnnnnnttttt Vt[] Rn - case IF_LS_2G: // LS_2G .Q.............. ...Sssnnnnnttttt Vt[] Rn + case IF_LS_2F: // LS_2F .Q.............. xx.Sssnnnnnttttt Vt[] Rn + case IF_LS_2G: // LS_2G .Q.............. xx.Sssnnnnnttttt Vt[] Rn elemsize = id->idOpSize(); index = id->idSmallCns(); code = emitInsCode(ins, fmt); @@ -11645,8 +11645,8 @@ void emitter::emitDispIns( } break; - case IF_LS_2F: // LS_2F .Q.............. ...Sssnnnnnttttt Vt[] Rn - case IF_LS_2G: // LS_2G .Q.............. ...Sssnnnnnttttt Vt[] Rn + case IF_LS_2F: // LS_2F .Q.............. xx.Sssnnnnnttttt Vt[] Rn + case IF_LS_2G: // LS_2G .Q.............. xx.Sssnnnnnttttt Vt[] Rn registerListSize = insGetLoadStoreRegisterListSize(id->idIns()); elemsize = id->idOpSize(); emitDispVectorElemList(id->idReg1(), registerListSize, elemsize, id->idSmallCns(), true); diff --git a/src/coreclr/src/jit/emitfmtsarm64.h b/src/coreclr/src/jit/emitfmtsarm64.h index c0fd69e..4013026 100644 --- a/src/coreclr/src/jit/emitfmtsarm64.h +++ b/src/coreclr/src/jit/emitfmtsarm64.h @@ -138,8 +138,8 @@ IF_DEF(LS_2D, IS_NONE, NONE) // LS_2D .Q.............. ....ssnnnnnttttt V // Load single structure and replicate base register IF_DEF(LS_2E, IS_NONE, NONE) // LS_2E .Q.............. ....ssnnnnnttttt Vt Rn Load/Store multiple structures post-indexed by an immediate // Load single structure and replicate post-indexed by an immediate -IF_DEF(LS_2F, IS_NONE, NONE) // LS_2F .Q.............. ...Sssnnnnnttttt Vt[] Rn Load/Store single structure base register -IF_DEF(LS_2G, IS_NONE, NONE) // LS_2G .Q.............. ...Sssnnnnnttttt Vt[] Rn Load/Store single structure post-indexed by an immediate +IF_DEF(LS_2F, IS_NONE, NONE) // LS_2F .Q.............. xx.Sssnnnnnttttt Vt[] Rn Load/Store single structure base register +IF_DEF(LS_2G, IS_NONE, NONE) // LS_2G .Q.............. xx.Sssnnnnnttttt Vt[] Rn Load/Store single structure post-indexed by an immediate IF_DEF(LS_3A, IS_NONE, NONE) // LS_3A .X.......X.mmmmm xxxS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {} IF_DEF(LS_3B, IS_NONE, NONE) // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn IF_DEF(LS_3C, IS_NONE, NONE) // LS_3C X.........iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh) diff --git a/src/coreclr/src/jit/hwintrinsic.cpp b/src/coreclr/src/jit/hwintrinsic.cpp index 0aef729..4b8848b 100644 --- a/src/coreclr/src/jit/hwintrinsic.cpp +++ b/src/coreclr/src/jit/hwintrinsic.cpp @@ -61,12 +61,11 @@ var_types Compiler::getBaseTypeFromArgIfNeeded(NamedIntrinsic intrinsic, { HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsic); - if (category == HW_Category_MemoryStore || HWIntrinsicInfo::BaseTypeFromSecondArg(intrinsic) || - HWIntrinsicInfo::BaseTypeFromFirstArg(intrinsic)) + if (HWIntrinsicInfo::BaseTypeFromSecondArg(intrinsic) || HWIntrinsicInfo::BaseTypeFromFirstArg(intrinsic)) { CORINFO_ARG_LIST_HANDLE arg = sig->args; - if ((category == HW_Category_MemoryStore) || HWIntrinsicInfo::BaseTypeFromSecondArg(intrinsic)) + if (HWIntrinsicInfo::BaseTypeFromSecondArg(intrinsic)) { arg = info.compCompHnd->getArgNext(arg); } diff --git a/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp index 178f760..6853b597 100644 --- a/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp @@ -301,6 +301,10 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GetEmitter()->emitIns_R_R_R_R(ins, emitSize, targetReg, op2Reg, op3Reg, op1Reg); break; + case NI_AdvSimd_Store: + GetEmitter()->emitIns_R_R(ins, emitSize, op2Reg, op1Reg, opt); + break; + default: unreached(); } diff --git a/src/coreclr/src/jit/hwintrinsiclistarm64.h b/src/coreclr/src/jit/hwintrinsiclistarm64.h index 8be2793..ac2a571 100644 --- a/src/coreclr/src/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/src/jit/hwintrinsiclistarm64.h @@ -97,6 +97,7 @@ HARDWARE_INTRINSIC(AdvSimd, Or, - HARDWARE_INTRINSIC(AdvSimd, OrNot, -1, -1, 2, {INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize) HARDWARE_INTRINSIC(AdvSimd, PopCount, -1, -1, 1, {INS_cnt, INS_cnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize) HARDWARE_INTRINSIC(AdvSimd, SqrtScalar, -1, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fsqrt, INS_fsqrt}, HW_Category_SIMDScalar, HW_Flag_NoContainment) +HARDWARE_INTRINSIC(AdvSimd, Store, -1, -1, 2, {INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_UnfixedSIMDSize|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(AdvSimd, Subtract, -1, -1, 2, {INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_fsub, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize) HARDWARE_INTRINSIC(AdvSimd, SubtractScalar, -1, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sub, INS_sub, INS_fsub, INS_fsub}, HW_Category_SIMDScalar, HW_Flag_NoContainment) HARDWARE_INTRINSIC(AdvSimd, Xor, -1, -1, 2, {INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize|HW_Flag_Commutative) diff --git a/src/coreclr/src/jit/hwintrinsiclistxarch.h b/src/coreclr/src/jit/hwintrinsiclistxarch.h index 9cb005b..de3add9 100644 --- a/src/coreclr/src/jit/hwintrinsiclistxarch.h +++ b/src/coreclr/src/jit/hwintrinsiclistxarch.h @@ -155,13 +155,13 @@ HARDWARE_INTRINSIC(SSE_ReciprocalSqrtScalar, "ReciprocalS HARDWARE_INTRINSIC(SSE_Shuffle, "Shuffle", SSE, -1, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_shufps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) HARDWARE_INTRINSIC(SSE_Sqrt, "Sqrt", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_SqrtScalar, "SqrtScalar", SSE, -1, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_Store, "Store", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movups, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_StoreAligned, "StoreAligned", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movaps, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_StoreAlignedNonTemporal, "StoreAlignedNonTemporal", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movntps, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_Store, "Store", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movups, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(SSE_StoreAligned, "StoreAligned", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movaps, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(SSE_StoreAlignedNonTemporal, "StoreAlignedNonTemporal", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movntps, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE_StoreFence, "StoreFence", SSE, -1, 0, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_StoreHigh, "StoreHigh", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movhps, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_StoreLow, "StoreLow", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movlps, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_StoreScalar, "StoreScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_StoreHigh, "StoreHigh", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movhps, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(SSE_StoreLow, "StoreLow", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movlps, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(SSE_StoreScalar, "StoreScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE_Subtract, "Subtract", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE_SubtractScalar, "SubtractScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE_UnpackHigh, "UnpackHigh", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_unpckhps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) @@ -245,7 +245,7 @@ HARDWARE_INTRINSIC(SSE2_LoadHigh, "LoadHigh", HARDWARE_INTRINSIC(SSE2_LoadLow, "LoadLow", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movlpd}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_LoadScalarVector128, "LoadScalarVector128", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_movd, INS_movq, INS_movq, INS_invalid, INS_movsdsse2}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_LoadVector128, "LoadVector128", SSE2, -1, 16, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_invalid, INS_movupd}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_MaskMove, "MaskMove", SSE2, -1, 16, 3, {INS_maskmovdqu, INS_maskmovdqu, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_MaskMove, "MaskMove", SSE2, -1, 16, 3, {INS_maskmovdqu, INS_maskmovdqu, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE2_Max, "Max", SSE2, -1, 16, 2, {INS_invalid, INS_pmaxub, INS_pmaxsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) HARDWARE_INTRINSIC(SSE2_MemoryFence, "MemoryFence", SSE2, -1, 0, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_MaxScalar, "MaxScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) @@ -272,13 +272,13 @@ HARDWARE_INTRINSIC(SSE2_ShuffleHigh, "ShuffleHigh HARDWARE_INTRINSIC(SSE2_ShuffleLow, "ShuffleLow", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_pshuflw, INS_pshuflw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) HARDWARE_INTRINSIC(SSE2_Sqrt, "Sqrt", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_SqrtScalar, "SqrtScalar", SSE2, -1, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_Store, "Store", SSE2, -1, 16, 2, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_invalid, INS_movupd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_StoreAligned, "StoreAligned", SSE2, -1, 16, 2, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_invalid, INS_movapd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_StoreAlignedNonTemporal, "StoreAlignedNonTemporal", SSE2, -1, 16, 2, {INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_invalid, INS_movntpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_StoreHigh, "StoreHigh", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movhpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_StoreLow, "StoreLow", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movlpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_StoreNonTemporal, "StoreNonTemporal", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movnti, INS_movnti, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(SSE2_StoreScalar, "StoreScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movq, INS_movq, INS_invalid, INS_movsdsse2}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_Store, "Store", SSE2, -1, 16, 2, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_invalid, INS_movupd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(SSE2_StoreAligned, "StoreAligned", SSE2, -1, 16, 2, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_invalid, INS_movapd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(SSE2_StoreAlignedNonTemporal, "StoreAlignedNonTemporal", SSE2, -1, 16, 2, {INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_invalid, INS_movntpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(SSE2_StoreHigh, "StoreHigh", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movhpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(SSE2_StoreLow, "StoreLow", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movlpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(SSE2_StoreNonTemporal, "StoreNonTemporal", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movnti, INS_movnti, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(SSE2_StoreScalar, "StoreScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movq, INS_movq, INS_invalid, INS_movsdsse2}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE2_Subtract, "Subtract", SSE2, -1, 16, 2, {INS_psubb, INS_psubb, INS_psubw, INS_psubw, INS_psubd, INS_psubd, INS_psubq, INS_psubq, INS_invalid, INS_subpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE2_SubtractSaturate, "SubtractSaturate", SSE2, -1, 16, 2, {INS_psubsb, INS_psubusb, INS_psubsw, INS_psubusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE2_SubtractScalar, "SubtractScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) @@ -297,7 +297,7 @@ HARDWARE_INTRINSIC(SSE2_X64_ConvertToUInt64, "ConvertToUI HARDWARE_INTRINSIC(SSE2_X64_ConvertScalarToVector128Double, "ConvertScalarToVector128Double", SSE2_X64, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2sd, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE2_X64_ConvertScalarToVector128Int64, "ConvertScalarToVector128Int64", SSE2_X64, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(SSE2_X64_ConvertScalarToVector128UInt64, "ConvertScalarToVector128UInt64", SSE2_X64, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(SSE2_X64_StoreNonTemporal, "StoreNonTemporal", SSE2_X64, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movnti, INS_movnti, INS_invalid, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(SSE2_X64_StoreNonTemporal, "StoreNonTemporal", SSE2_X64, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movnti, INS_movnti, INS_invalid, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Intrinsic ID Function name ISA ival SIMD size NumArg instructions Category Flags @@ -447,9 +447,9 @@ HARDWARE_INTRINSIC(AVX_RoundToPositiveInfinity, "RoundToPosi HARDWARE_INTRINSIC(AVX_RoundToZero, "RoundToZero", AVX, 11, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(AVX_Shuffle, "Shuffle", AVX, -1, 32, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_shufps, INS_shufpd}, HW_Category_IMM, HW_Flag_NoRMWSemantics|HW_Flag_FullRangeIMM) HARDWARE_INTRINSIC(AVX_Sqrt, "Sqrt", AVX, -1, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtps, INS_sqrtpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX_Store, "Store", AVX, -1, 32, 2, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX_StoreAligned, "StoreAligned", AVX, -1, 32, 2, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movaps, INS_movapd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX_StoreAlignedNonTemporal, "StoreAlignedNonTemporal", AVX, -1, 32, 2, {INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntps, INS_movntpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(AVX_Store, "Store", AVX, -1, 32, 2, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(AVX_StoreAligned, "StoreAligned", AVX, -1, 32, 2, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movaps, INS_movapd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(AVX_StoreAlignedNonTemporal, "StoreAlignedNonTemporal", AVX, -1, 32, 2, {INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntps, INS_movntpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(AVX_Subtract, "Subtract", AVX, -1, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subps, INS_subpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX_TestC, "TestC", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_UnfixedSIMDSize|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(AVX_TestNotZAndNotC, "TestNotZAndNotC", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_UnfixedSIMDSize|HW_Flag_BaseTypeFromFirstArg) diff --git a/src/coreclr/src/jit/instrsarm64.h b/src/coreclr/src/jit/instrsarm64.h index 6958660..f41a704 100644 --- a/src/coreclr/src/jit/instrsarm64.h +++ b/src/coreclr/src/jit/instrsarm64.h @@ -87,65 +87,81 @@ INST6(sub, "sub", 0, 0, IF_EN6A, 0x4B000000, 0x4B000000, 0x4B200000, // enum name FP LD/ST LS_2D LS_3F LS_2E LS_2F LS_3G LS_2G INST6(ld1, "ld1", 0, LD, IF_EN6B, 0x0C407000, 0x0CC07000, 0x0CDF7000, 0x0D400000, 0x0DC00000, 0x0DDF0000) + // C7.2.170 LD1 (multiple structures, one register variant) // ld1 {Vt},[Xn] LS_2D 0Q00110001000000 0111ssnnnnnttttt 0C40 7000 base register // ld1 {Vt},[Xn],Xm LS_3F 0Q001100110mmmmm 0111ssnnnnnttttt 0CC0 7000 post-indexed by a register // ld1 {Vt},[Xn],#imm LS_2E 0Q00110011011111 0111ssnnnnnttttt 0CDF 7000 post-indexed by an immediate + // C7.2.171 LD1 (single structure) // ld1 {Vt}[],[Xn] LS_2F 0Q00110101000000 xx0Sssnnnnnttttt 0D40 0000 base register // ld1 {Vt}[],[Xn],Xm LS_3G 0Q001101110mmmmm xx0Sssnnnnnttttt 0DC0 0000 post-indexed by a register // ld1 {Vt}[],[Xn],#imm LS_2G 0Q00110111011111 xx0Sssnnnnnttttt 0DDF 0000 post-indexed by an immediate INST6(ld2, "ld2", 0, LD, IF_EN6B, 0x0C408000, 0x0CC08000, 0x0CDF8000, 0x0D600000, 0x0DE00000, 0x0DFF0000) + // C7.2.173 LD2 (multiple structures) // ld2 {Vt,Vt2},[Xn] LS_2D 0Q00110001000000 1000ssnnnnnttttt 0C40 8000 base register // ld2 {Vt,Vt2},[Xn],Xm LS_3F 0Q001100110mmmmm 1000ssnnnnnttttt 0CC0 8000 post-indexed by a register // ld2 {Vt,Vt2},[Xn],#imm LS_2E 0Q001100110mmmmm 1000ssnnnnnttttt 0CDF 8000 post-indexed by an immediate + // C7.2.174 LD2 (single structure) // ld2 {Vt,Vt2}[],[Xn] LS_2F 0Q00110101100000 xx0Sssnnnnnttttt 0D60 0000 base register // ld2 {Vt,Vt2}[],[Xn],Xm LS_3G 0Q001101111mmmmm xx0Sssnnnnnttttt 0DE0 0000 post-indexed by a register // ld2 {Vt,Vt2}[],[Xn],#imm LS_2G 0Q00110111111111 xx0Sssnnnnnttttt 0DFF 0000 post-indexed by an immediate INST6(ld3, "ld3", 0, LD, IF_EN6B, 0x0C404000, 0x0CC04000, 0x0CDF4000, 0x0D402000, 0x0DC02000, 0x0DDF2000) + // C7.2.176 LD3 (multiple structures) // ld3 {Vt-Vt3},[Xn] LS_2D 0Q00110001000000 0100ssnnnnnttttt 0C40 4000 base register // ld3 {Vt-Vt3},[Xn],Xm LS_3F 0Q001100110mmmmm 0100ssnnnnnttttt 0CC0 4000 post-indexed by a register // ld3 {Vt-Vt3},[Xn],#imm LS_2E 0Q001100110mmmmm 0100ssnnnnnttttt 0CDF 4000 post-indexed by an immediate + // C7.2.177 LD3 (single structure) // ld3 {Vt-Vt3}[],[Xn] LS_2F 0Q00110101000000 xx1Sssnnnnnttttt 0D40 2000 base register // ld3 {Vt-Vt3}[],[Xn],Xm LS_3G 0Q001101110mmmmm xx1Sssnnnnnttttt 0DC0 2000 post-indexed by a register // ld3 {Vt-Vt3}[],[Xn],#imm LS_2G 0Q00110111011111 xx1Sssnnnnnttttt 0DDF 2000 post-indexed by an immediate INST6(ld4, "ld4", 0, LD, IF_EN6B, 0x0C400000, 0x0CC00000, 0x0CDF0000, 0x0D602000, 0x0DE02000, 0x0DFF2000) + // C7.2.179 LD4 (multiple structures) // ld4 {Vt-Vt4},[Xn] LS_2D 0Q00110001000000 0000ssnnnnnttttt 0C40 0000 base register // ld4 {Vt-Vt4},[Xn],Xm LS_3F 0Q001100110mmmmm 0000ssnnnnnttttt 0CC0 0000 post-indexed by a register // ld4 {Vt-Vt4},[Xn],#imm LS_2E 0Q00110011011111 0000ssnnnnnttttt 0CDF 0000 post-indexed by an immediate + // C7.2.180 LD4 (single structure) // ld4 {Vt-Vt4}[],[Xn] LS_2F 0Q00110101100000 xx1Sssnnnnnttttt 0D60 2000 base register // ld4 {Vt-Vt4}[],[Xn],Xm LS_3G 0Q001101111mmmmm xx1Sssnnnnnttttt 0DE0 2000 post-indexed by a register // ld4 {Vt-Vt4}[],[Xn],#imm LS_2G 0Q00110111111111 xx1Sssnnnnnttttt 0DFF 2000 post-indexed by an immediate INST6(st1, "st1", 0, LD, IF_EN6B, 0x0C007000, 0x0C807000, 0x0C9F7000, 0x0D000000, 0x0D800000, 0x0D9F0000) + // C7.2.313 ST1 (multiple structures, one register variant) // st1 {Vt},[Xn] LS_2D 0Q00110000000000 0111ssnnnnnttttt 0C00 7000 base register // st1 {Vt},[Xn],Xm LS_3F 0Q001100100mmmmm 0111ssnnnnnttttt 0C80 7000 post-indexed by a register // st1 {Vt},[Xn],#imm LS_2E 0Q00110010011111 0111ssnnnnnttttt 0C9F 7000 post-indexed by an immediate + // C7.2.314 ST1 (single structure) // st1 {Vt}[],[Xn] LS_2F 0Q00110100000000 xx0Sssnnnnnttttt 0D00 0000 base register // st1 {Vt}[],[Xn],Xm LS_3G 0Q001101100mmmmm xx0Sssnnnnnttttt 0D80 0000 post-indexed by a register // st1 {Vt}[],[Xn],#imm LS_2G 0Q00110110011111 xx0Sssnnnnnttttt 0D9F 0000 post-indexed by an immediate INST6(st2, "st2", 0, ST, IF_EN6B, 0x0C008000, 0x0C808000, 0x0C9F8000, 0x0D200000, 0x0DA00000, 0x0DBF0000) + // C7.2.315 ST2 (multiple structures) // st2 {Vt,Vt2},[Xn] LS_2D 0Q00110000000000 1000ssnnnnnttttt 0C00 8000 base register // st2 {Vt,Vt2},[Xn],Xm LS_3F 0Q001100100mmmmm 1000ssnnnnnttttt 0C80 8000 post-indexed by a register // st2 {Vt,Vt2},[Xn],#imm LS_2E 0Q00110010011111 1000ssnnnnnttttt 0C9F 8000 post-indexed by an immediate + // C7.2.316 ST2 (single structure) // st2 {Vt,Vt2}[],[Xn] LS_2F 0Q00110100100000 xx0Sssnnnnnttttt 0D20 0000 base register // st2 {Vt,Vt2}[],[Xn],Xm LS_3G 0Q001101101mmmmm xx0Sssnnnnnttttt 0DA0 0000 post-indexed by a register // st2 {Vt,Vt2}[],[Xn],#imm LS_2G 0Q00110110111111 xx0Sssnnnnnttttt 0DBF 0000 post-indexed by an immediate INST6(st3, "st3", 0, ST, IF_EN6B, 0x0C004000, 0x0C804000, 0x0C9F4000, 0x0D002000, 0x0D802000, 0x0D9F2000) + // C7.2.317 ST3 (multiple structures) // st3 {Vt-Vt3},[Xn] LS_2D 0Q00110000000000 0100ssnnnnnttttt 0C00 4000 base register // st3 {Vt-Vt3},[Xn],Xm LS_3F 0Q001100100mmmmm 0100ssnnnnnttttt 0C80 4000 post-indexed by a register // st3 {Vt-Vt3},[Xn],#imm LS_2E 0Q00110010011111 0100ssnnnnnttttt 0C9F 4000 post-indexed by an immediate + // C7.2.318 ST3 (single structure) // st3 {Vt-Vt3}[],[Xn] LS_2F 0Q00110100000000 xx1Sssnnnnnttttt 0D00 2000 base register // st3 {Vt-Vt3}[],[Xn],Xm LS_3G 0Q001101100mmmmm xx1Sssnnnnnttttt 0D80 2000 post-indexed by a register // st3 {Vt-Vt3}[],[Xn],#imm LS_2G 0Q00110110011111 xx1Sssnnnnnttttt 0D9F 2000 post-indexed by an immediate INST6(st4, "st4", 0, ST, IF_EN6B, 0x0C000000, 0x0C800000, 0x0C9F0000, 0x0D202000, 0x0DA02000, 0x0DBF2000) + // C7.2.319 ST4 (multiple structures) // st4 {Vt-Vt4},[Xn] LS_2D 0Q00110000000000 0000ssnnnnnttttt 0C00 0000 base register // st4 {Vt-Vt4},[Xn],Xm LS_3F 0Q001100100mmmmm 0000ssnnnnnttttt 0C80 0000 post-indexed by a register // st4 {Vt-Vt4},[Xn],#imm LS_2E 0Q00110010011111 0000ssnnnnnttttt 0C9F 0000 post-indexed by an immediate + // C7.2.320 ST4 (single structure) // st4 {Vt-Vt4}[],[Xn] LS_2F 0Q00110100100000 xx1Sssnnnnnttttt 0D20 2000 base register // st4 {Vt-Vt4}[],[Xn],Xm LS_3G 0Q001101101mmmmm xx1Sssnnnnnttttt 0DA0 2000 post-indexed by a register // st4 {Vt-Vt4}[],[Xn],#imm LS_2G 0Q00110110111111 xx1Sssnnnnnttttt 0DBF 2000 post-indexed by an immediate @@ -438,51 +454,61 @@ INST3(mvn, "mvn", 0, 0, IF_EN3I, 0x2A2003E0, 0x2A2003E0, 0x2E205800) // enum name FP LD/ST LS_2D LS_3F LS_2E INST3(ld1_2regs,"ld1", 0,LD, IF_EN3J, 0x0C40A000, 0x0CC0A000, 0x0CDFA000) + // C7.2.170 LD1 (multiple structures, two registers variant) // ld1 {Vt,Vt2},[Xn] LS_2D 0Q00110001000000 1010ssnnnnnttttt 0C40 A000 base register // ld1 {Vt,Vt2},[Xn],Xm LS_3F 0Q001100110mmmmm 1010ssnnnnnttttt 0CC0 A000 post-indexed by a register // ld1 {Vt,Vt2},[Xn],#imm LS_2E 0Q00110011011111 1010ssnnnnnttttt 0CDF A000 post-indexed by an immediate INST3(ld1_3regs,"ld1", 0,LD, IF_EN3J, 0x0C406000, 0x0CC06000, 0x0CDF6000) + // C7.2.170 LD1 (multiple structures, three registers variant) // ld1 {Vt-Vt3},[Xn] LS_2D 0Q00110001000000 0110ssnnnnnttttt 0C40 6000 base register // ld1 {Vt-Vt3},[Xn],Xm LS_3F 0Q001100110mmmmm 0110ssnnnnnttttt 0CC0 6000 post-indexed by a register // ld1 {Vt-Vt3},[Xn],#imm LS_2E 0Q00110011011111 0110ssnnnnnttttt 0CDF 6000 post-indexed by an immediate INST3(ld1_4regs,"ld1", 0,LD, IF_EN3J, 0x0C402000, 0x0CC02000, 0x0CDF2000) + // C7.2.170 LD1 (multiple structures, four registers variant) // ld1 {Vt-Vt4},[Xn] LS_2D 0Q00110001000000 0010ssnnnnnttttt 0C40 2000 base register // ld1 {Vt-Vt4},[Xn],Xm LS_3F 0Q001100110mmmmm 0010ssnnnnnttttt 0CC0 2000 post-indexed by a register // ld1 {Vt-Vt4},[Xn],#imm LS_2E 0Q00110011011111 0010ssnnnnnttttt 0CDF 2000 post-indexed by an immediate INST3(st1_2regs,"st1", 0,ST, IF_EN3J, 0x0C00A000, 0x0C80A000, 0x0C9FA000) + // C7.2.313 ST1 (multiple structures, two registers variant) // st1 {Vt,Vt2},[Xn] LS_2D 0Q00110000000000 1010ssnnnnnttttt 0C00 A000 base register // st1 {Vt,Vt2},[Xn],Xm LS_3F 0Q001100100mmmmm 1010ssnnnnnttttt 0C80 A000 post-indexed by a register // st1 {Vt,Vt2},[Xn],#imm LS_2E 0Q00110010011111 1010ssnnnnnttttt 0C9F A000 post-indexed by an immediate INST3(st1_3regs,"st1", 0,ST, IF_EN3J, 0x0C006000, 0x0C806000, 0x0C9F6000) + // C7.2.313 ST1 (multiple structures, three registers variant) // st1 {Vt-Vt3},[Xn] LS_2D 0Q00110000000000 0110ssnnnnnttttt 0C00 6000 base register // st1 {Vt-Vt3},[Xn],Xm LS_3F 0Q001100100mmmmm 0110XXnnnnnttttt 0C80 6000 post-indexed by a register // st1 {Vt-Vt3},[Xn],#imm LS_2E 0Q00110010011111 0110XXnnnnnttttt 0C9F 6000 post-indexed by an immediate INST3(st1_4regs,"st1", 0,ST, IF_EN3J, 0x0C002000, 0x0C802000, 0x0C9F2000) + // C7.2.313 ST1 (multiple structures, four registers variant) // st1 {Vt-Vt4},[Xn] LS_2D 0Q00110000000000 0010XXnnnnnttttt 0C00 2000 base register // st1 {Vt-Vt4},[Xn],Xm LS_3F 0Q001100100mmmmm 0010XXnnnnnttttt 0C80 2000 post-indexed by a register // st1 {Vt-Vt4},[Xn],#imm LS_2E 0Q00110010011111 0010XXnnnnnttttt 0C9F 2000 post-indexed by an immediate INST3(ld1r, "ld1r", 0,LD, IF_EN3J, 0x0D40C000, 0x0DC0C000, 0x0DDFC000) + // C7.2.172 LD1R // ld1r {Vt},[Xn] LS_2D 0Q00110101000000 1100ssnnnnnttttt 0D40 C000 base register // ld1r {Vt},[Xn],Xm LS_3F 0Q001101110mmmmm 1100ssnnnnnttttt 0DC0 C000 post-indexed by a register // ld1r {Vt},[Xn],#1 LS_2E 0Q00110111011111 1100ssnnnnnttttt 0DDF C000 post-indexed by an immediate INST3(ld2r, "ld2r", 0,LD, IF_EN3J, 0x0D60C000, 0x0DE0C000, 0x0DFFC000) + // C7.2.175 LD2R // ld2r {Vt,Vt2},[Xn] LS_2D 0Q00110101100000 1100ssnnnnnttttt 0D60 C000 base register // ld2r {Vt,Vt2},[Xn],Xm LS_3F 0Q001101111mmmmm 1100ssnnnnnttttt 0DE0 C000 post-indexed by a register // ld2r {Vt,Vt2},[Xn],#2 LS_2E 0Q00110111111111 1100ssnnnnnttttt 0DFF C000 post-indexed by an immediate INST3(ld3r, "ld3r", 0,LD, IF_EN3J, 0x0D40E000, 0x0DC0E000, 0x0DDFE000) + // C7.2.178 LD3R // ld3r {Vt-Vt3},[Xn] LS_2D 0Q00110101000000 1110ssnnnnnttttt 0D40 E000 base register // ld3r {Vt-Vt3},[Xn],Xm LS_3F 0Q001101110mmmmm 1110ssnnnnnttttt 0DC0 E000 post-indexed by a register // ld3r {Vt-Vt3},[Xn],#4 LS_2E 0Q00110111011111 1110ssnnnnnttttt 0DDF E000 post-indexed by an immediate INST3(ld4r, "ld4r", 0,LD, IF_EN3J, 0x0D60E000, 0x0DE0E000, 0x0DFFE000) + // C7.2.181 LD4R // ld4r {Vt-Vt4},[Xn] LS_2D 0Q00110101100000 1110ssnnnnnttttt 0D60 E000 base register // ld4r {Vt-Vt4},[Xn],Xm LS_3F 0Q001101111mmmmm 1110ssnnnnnttttt 0DE0 E000 post-indexed by a register // ld4r {Vt-Vt4},[Xn],#8 LS_2E 0Q00110111111111 1110ssnnnnnttttt 0DFF E000 post-indexed by an immediate diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_r.csproj b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_r.csproj index 07a3c59..c2bc7b3 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_r.csproj +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_r.csproj @@ -429,6 +429,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_ro.csproj b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_ro.csproj index 10562a5..a35c1c2 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_ro.csproj +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_ro.csproj @@ -429,6 +429,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Program.AdvSimd.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Program.AdvSimd.cs index dd20b98..f45f02c 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Program.AdvSimd.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Program.AdvSimd.cs @@ -433,6 +433,26 @@ namespace JIT.HardwareIntrinsics.Arm ["PopCount.Vector128.SByte"] = PopCount_Vector128_SByte, ["SqrtScalar.Vector64.Double"] = SqrtScalar_Vector64_Double, ["SqrtScalar.Vector64.Single"] = SqrtScalar_Vector64_Single, + ["Store.Vector64.Byte"] = Store_Vector64_Byte, + ["Store.Vector64.Double"] = Store_Vector64_Double, + ["Store.Vector64.Int16"] = Store_Vector64_Int16, + ["Store.Vector64.Int32"] = Store_Vector64_Int32, + ["Store.Vector64.Int64"] = Store_Vector64_Int64, + ["Store.Vector64.SByte"] = Store_Vector64_SByte, + ["Store.Vector64.Single"] = Store_Vector64_Single, + ["Store.Vector64.UInt16"] = Store_Vector64_UInt16, + ["Store.Vector64.UInt32"] = Store_Vector64_UInt32, + ["Store.Vector64.UInt64"] = Store_Vector64_UInt64, + ["Store.Vector128.Byte"] = Store_Vector128_Byte, + ["Store.Vector128.Double"] = Store_Vector128_Double, + ["Store.Vector128.Int16"] = Store_Vector128_Int16, + ["Store.Vector128.Int32"] = Store_Vector128_Int32, + ["Store.Vector128.Int64"] = Store_Vector128_Int64, + ["Store.Vector128.SByte"] = Store_Vector128_SByte, + ["Store.Vector128.Single"] = Store_Vector128_Single, + ["Store.Vector128.UInt16"] = Store_Vector128_UInt16, + ["Store.Vector128.UInt32"] = Store_Vector128_UInt32, + ["Store.Vector128.UInt64"] = Store_Vector128_UInt64, ["Subtract.Vector64.Byte"] = Subtract_Vector64_Byte, ["Subtract.Vector64.Int16"] = Subtract_Vector64_Int16, ["Subtract.Vector64.Int32"] = Subtract_Vector64_Int32, diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Byte.cs new file mode 100644 index 0000000..0c53a2b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Byte.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector128_Byte() + { + var test = new StoreUnaryOpTest__Store_Vector128_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector128_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector128_Byte testClass) + { + AdvSimd.Store((Byte*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector128_Byte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((Byte*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector128((Byte*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector128_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector128_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data1, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Byte*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Byte*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Byte*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Byte*)), + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Byte*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector128_Byte(); + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector128_Byte(); + + fixed (Vector128* pFld1 = &test._fld1) + { + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Byte*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Byte*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Byte*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Double.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Double.cs new file mode 100644 index 0000000..790527f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Double.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector128_Double() + { + var test = new StoreUnaryOpTest__Store_Vector128_Double(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector128_Double + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Double[] inArray1, Double[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector128_Double testClass) + { + AdvSimd.Store((Double*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector128_Double testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((Double*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector128((Double*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Double); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Double); + + private static Double[] _data1 = new Double[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector128_Double() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector128_Double() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + _dataTable = new DataTable(_data1, new Double[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((Double*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((Double*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Double*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Double*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Double*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Double*)), + AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((Double*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((Double*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Double*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((Double*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((Double*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector128_Double(); + AdvSimd.Store((Double*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector128_Double(); + + fixed (Vector128* pFld1 = &test._fld1) + { + AdvSimd.Store((Double*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Double*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((Double*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((Double*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Double*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((Double*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((Double*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Double*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + Double[] inArray1 = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Double[] inArray1 = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Int16.cs new file mode 100644 index 0000000..8028951 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Int16.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector128_Int16() + { + var test = new StoreUnaryOpTest__Store_Vector128_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector128_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector128_Int16 testClass) + { + AdvSimd.Store((Int16*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector128_Int16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((Int16*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector128((Int16*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector128_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector128_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Int16*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int16*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Int16*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int16*)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int16*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector128_Int16(); + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector128_Int16(); + + fixed (Vector128* pFld1 = &test._fld1) + { + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int16*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int16*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int16*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Int32.cs new file mode 100644 index 0000000..d2e2aeb --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Int32.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector128_Int32() + { + var test = new StoreUnaryOpTest__Store_Vector128_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector128_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector128_Int32 testClass) + { + AdvSimd.Store((Int32*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector128_Int32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((Int32*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector128((Int32*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector128_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector128_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Int32*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int32*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Int32*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int32*)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int32*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector128_Int32(); + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector128_Int32(); + + fixed (Vector128* pFld1 = &test._fld1) + { + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int32*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int32*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int32*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Int64.cs new file mode 100644 index 0000000..8cfa926 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Int64.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector128_Int64() + { + var test = new StoreUnaryOpTest__Store_Vector128_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector128_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector128_Int64 testClass) + { + AdvSimd.Store((Int64*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector128_Int64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((Int64*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector128((Int64*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector128_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector128_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Int64*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int64*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Int64*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int64*)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int64*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector128_Int64(); + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector128_Int64(); + + fixed (Vector128* pFld1 = &test._fld1) + { + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int64*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int64*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Int64*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.SByte.cs new file mode 100644 index 0000000..77aa5d0 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.SByte.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector128_SByte() + { + var test = new StoreUnaryOpTest__Store_Vector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector128_SByte testClass) + { + AdvSimd.Store((SByte*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((SByte*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector128((SByte*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector128_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector128_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(SByte*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(SByte*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(SByte*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(SByte*)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((SByte*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector128_SByte(); + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + { + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((SByte*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((SByte*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((SByte*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Single.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Single.cs new file mode 100644 index 0000000..9aaf745 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.Single.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector128_Single() + { + var test = new StoreUnaryOpTest__Store_Vector128_Single(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector128_Single + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] inArray1, Single[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector128_Single testClass) + { + AdvSimd.Store((Single*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector128_Single testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((Single*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector128((Single*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Single); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Single); + + private static Single[] _data1 = new Single[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector128_Single() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector128_Single() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } + _dataTable = new DataTable(_data1, new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((Single*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((Single*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Single*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Single*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Single*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Single*)), + AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((Single*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((Single*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Single*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((Single*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((Single*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector128_Single(); + AdvSimd.Store((Single*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector128_Single(); + + fixed (Vector128* pFld1 = &test._fld1) + { + AdvSimd.Store((Single*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Single*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((Single*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((Single*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Single*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((Single*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((Single*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((Single*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + Single[] inArray1 = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Single[] inArray1 = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.UInt16.cs new file mode 100644 index 0000000..258cce1 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.UInt16.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector128_UInt16() + { + var test = new StoreUnaryOpTest__Store_Vector128_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector128_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector128_UInt16 testClass) + { + AdvSimd.Store((UInt16*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector128_UInt16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((UInt16*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt16*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector128_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector128_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data1, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(UInt16*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt16*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(UInt16*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt16*)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt16*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector128_UInt16(); + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector128_UInt16(); + + fixed (Vector128* pFld1 = &test._fld1) + { + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt16*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt16*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt16*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.UInt32.cs new file mode 100644 index 0000000..57110a4 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.UInt32.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector128_UInt32() + { + var test = new StoreUnaryOpTest__Store_Vector128_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector128_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector128_UInt32 testClass) + { + AdvSimd.Store((UInt32*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector128_UInt32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((UInt32*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt32*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector128_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector128_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data1, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(UInt32*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt32*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(UInt32*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt32*)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt32*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector128_UInt32(); + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector128_UInt32(); + + fixed (Vector128* pFld1 = &test._fld1) + { + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt32*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt32*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt32*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.UInt64.cs new file mode 100644 index 0000000..e766b14 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector128.UInt64.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector128_UInt64() + { + var test = new StoreUnaryOpTest__Store_Vector128_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector128_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector128_UInt64 testClass) + { + AdvSimd.Store((UInt64*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector128_UInt64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((UInt64*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt64*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector128_UInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector128_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data1, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(UInt64*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt64*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(UInt64*), typeof(Vector128) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt64*)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt64*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector128_UInt64(); + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector128_UInt64(); + + fixed (Vector128* pFld1 = &test._fld1) + { + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt64*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt64*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, AdvSimd.LoadVector128((UInt64*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Byte.cs new file mode 100644 index 0000000..161b1ee --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Byte.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector64_Byte() + { + var test = new StoreUnaryOpTest__Store_Vector64_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector64_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector64_Byte testClass) + { + AdvSimd.Store((Byte*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector64_Byte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((Byte*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector64((Byte*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector64_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector64_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data1, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Byte*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Byte*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Byte*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Byte*)), + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Byte*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector64_Byte(); + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector64_Byte(); + + fixed (Vector64* pFld1 = &test._fld1) + { + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Byte*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Byte*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((Byte*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Byte*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Double.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Double.cs new file mode 100644 index 0000000..6d70978 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Double.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector64_Double() + { + var test = new StoreUnaryOpTest__Store_Vector64_Double(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector64_Double + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Double[] inArray1, Double[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector64_Double testClass) + { + AdvSimd.Store((Double*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector64_Double testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((Double*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector64((Double*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Double); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Double); + + private static Double[] _data1 = new Double[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector64_Double() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector64_Double() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + _dataTable = new DataTable(_data1, new Double[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((Double*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((Double*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Double*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Double*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Double*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Double*)), + AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((Double*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((Double*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Double*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((Double*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((Double*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector64_Double(); + AdvSimd.Store((Double*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector64_Double(); + + fixed (Vector64* pFld1 = &test._fld1) + { + AdvSimd.Store((Double*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Double*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((Double*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((Double*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Double*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((Double*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((Double*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Double*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + Double[] inArray1 = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Double[] inArray1 = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Int16.cs new file mode 100644 index 0000000..8e1c682 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Int16.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector64_Int16() + { + var test = new StoreUnaryOpTest__Store_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector64_Int16 testClass) + { + AdvSimd.Store((Int16*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((Int16*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector64((Int16*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Int16*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int16*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Int16*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int16*)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int16*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector64_Int16(); + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + { + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int16*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int16*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((Int16*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int16*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Int32.cs new file mode 100644 index 0000000..20c186f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Int32.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector64_Int32() + { + var test = new StoreUnaryOpTest__Store_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector64_Int32 testClass) + { + AdvSimd.Store((Int32*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((Int32*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector64((Int32*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Int32*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int32*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Int32*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int32*)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int32*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector64_Int32(); + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + { + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int32*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int32*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((Int32*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int32*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Int64.cs new file mode 100644 index 0000000..c3109ec --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Int64.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector64_Int64() + { + var test = new StoreUnaryOpTest__Store_Vector64_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector64_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector64_Int64 testClass) + { + AdvSimd.Store((Int64*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector64_Int64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((Int64*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector64((Int64*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector64_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector64_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Int64*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int64*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Int64*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int64*)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int64*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector64_Int64(); + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector64_Int64(); + + fixed (Vector64* pFld1 = &test._fld1) + { + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int64*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int64*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((Int64*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Int64*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.SByte.cs new file mode 100644 index 0000000..906e5ab --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.SByte.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector64_SByte() + { + var test = new StoreUnaryOpTest__Store_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector64_SByte testClass) + { + AdvSimd.Store((SByte*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((SByte*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector64((SByte*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(SByte*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(SByte*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(SByte*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(SByte*)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((SByte*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector64_SByte(); + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + { + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((SByte*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((SByte*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((SByte*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((SByte*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Single.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Single.cs new file mode 100644 index 0000000..6a13a0d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.Single.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector64_Single() + { + var test = new StoreUnaryOpTest__Store_Vector64_Single(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector64_Single + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] inArray1, Single[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector64_Single testClass) + { + AdvSimd.Store((Single*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector64_Single testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((Single*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector64((Single*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Single); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Single); + + private static Single[] _data1 = new Single[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector64_Single() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector64_Single() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } + _dataTable = new DataTable(_data1, new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((Single*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((Single*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Single*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Single*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(Single*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Single*)), + AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((Single*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((Single*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Single*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((Single*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((Single*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector64_Single(); + AdvSimd.Store((Single*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector64_Single(); + + fixed (Vector64* pFld1 = &test._fld1) + { + AdvSimd.Store((Single*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Single*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((Single*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((Single*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Single*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((Single*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((Single*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((Single*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + Single[] inArray1 = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Single[] inArray1 = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.UInt16.cs new file mode 100644 index 0000000..3aa4af0 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.UInt16.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector64_UInt16() + { + var test = new StoreUnaryOpTest__Store_Vector64_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector64_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector64_UInt16 testClass) + { + AdvSimd.Store((UInt16*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector64_UInt16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((UInt16*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt16*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector64_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector64_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data1, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(UInt16*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt16*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(UInt16*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt16*)), + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt16*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector64_UInt16(); + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector64_UInt16(); + + fixed (Vector64* pFld1 = &test._fld1) + { + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt16*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt16*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((UInt16*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt16*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.UInt32.cs new file mode 100644 index 0000000..dc0d73f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.UInt32.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector64_UInt32() + { + var test = new StoreUnaryOpTest__Store_Vector64_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector64_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector64_UInt32 testClass) + { + AdvSimd.Store((UInt32*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector64_UInt32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((UInt32*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt32*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector64_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector64_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data1, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(UInt32*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt32*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(UInt32*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt32*)), + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt32*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector64_UInt32(); + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector64_UInt32(); + + fixed (Vector64* pFld1 = &test._fld1) + { + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt32*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt32*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((UInt32*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt32*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.UInt64.cs new file mode 100644 index 0000000..6a2ba8c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Store.Vector64.UInt64.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 Store_Vector64_UInt64() + { + var test = new StoreUnaryOpTest__Store_Vector64_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__Store_Vector64_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.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 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__Store_Vector64_UInt64 testClass) + { + AdvSimd.Store((UInt64*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__Store_Vector64_UInt64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((UInt64*)testClass._dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt64*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__Store_Vector64_UInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public StoreUnaryOpTest__Store_Vector64_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data1, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, Unsafe.Read>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(UInt64*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt64*)), + Unsafe.Read>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof(AdvSimd).GetMethod(nameof(AdvSimd.Store), new Type[] { typeof(UInt64*), typeof(Vector64) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt64*)), + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt64*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)); + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__Store_Vector64_UInt64(); + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__Store_Vector64_UInt64(); + + fixed (Vector64* pFld1 = &test._fld1) + { + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt64*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt64*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + AdvSimd.Store((UInt64*)_dataTable.outArrayPtr, AdvSimd.LoadVector64((UInt64*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Store)}(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/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx index 632dc3e..53d979a 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx @@ -508,6 +508,26 @@ private static readonly (string templateFileName, Dictionary tem ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "PopCount_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PopCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitCount(firstOp[i]) != result[i]"}), ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "SqrtScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SqrtScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Sqrt(firstOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "SqrtScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SqrtScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/StoreUnOpTest.template b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/StoreUnOpTest.template new file mode 100644 index 0000000..4cc48ea --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/StoreUnOpTest.template @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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 StoreUnaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if ({LoadIsa}.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if ({LoadIsa}.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if ({LoadIsa}.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if ({LoadIsa}.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if ({LoadIsa}.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + 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 StoreUnaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario(StoreUnaryOpTest__{TestName} testClass) + { + {Isa}.{Method}(({RetBaseType}*)testClass._dataTable.outArrayPtr, _fld1); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(StoreUnaryOpTest__{TestName} testClass) + { + fixed ({Op1VectorType}<{Op1BaseType}>* pFld1 = &_fld1) + { + {Isa}.{Method}(({RetBaseType}*)testClass._dataTable.outArrayPtr, {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(pFld1))); + + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + + private static {Op1VectorType}<{Op1BaseType}> _clsVar1; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + + private DataTable _dataTable; + + static StoreUnaryOpTest__{TestName}() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _clsVar1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + } + + public StoreUnaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + _dataTable = new DataTable(_data1, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + {Isa}.{Method}(({RetBaseType}*)_dataTable.outArrayPtr, Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr)); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + {Isa}.{Method}(({RetBaseType}*)_dataTable.outArrayPtr, {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArray1Ptr))); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({RetBaseType}*), typeof({Op1VectorType}<{Op1BaseType}>) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof({RetBaseType}*)), + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({RetBaseType}*), typeof({Op1VectorType}<{Op1BaseType}>) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof({RetBaseType}*)), + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArray1Ptr)) + }); + + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + {Isa}.{Method}(({RetBaseType}*)_dataTable.outArrayPtr, _clsVar1); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed ({Op1VectorType}<{Op1BaseType}>* pClsVar1 = &_clsVar1) + { + {Isa}.{Method}(({Op1BaseType}*)_dataTable.outArrayPtr, {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(pClsVar1))); + + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + {Isa}.{Method}(({RetBaseType}*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArray1Ptr)); + {Isa}.{Method}(({RetBaseType}*)_dataTable.outArrayPtr, op1); + + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new StoreUnaryOpTest__{TestName}(); + {Isa}.{Method}(({RetBaseType}*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new StoreUnaryOpTest__{TestName}(); + + fixed ({Op1VectorType}<{Op1BaseType}>* pFld1 = &test._fld1) + { + {Isa}.{Method}(({RetBaseType}*)_dataTable.outArrayPtr, {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(pFld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + {Isa}.{Method}(({RetBaseType}*)_dataTable.outArrayPtr, _fld1); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed ({Op1VectorType}<{Op1BaseType}>* pFld1 = &_fld1) + { + {Isa}.{Method}(({RetBaseType}*)_dataTable.outArrayPtr, {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(pFld1))); + + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + {Isa}.{Method}(({RetBaseType}*)_dataTable.outArrayPtr, test._fld1); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + {Isa}.{Method}(({RetBaseType}*)_dataTable.outArrayPtr, {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(&test._fld1))); + + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; 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; + } + } + } +} 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 a51ae8b..072b525 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 @@ -605,6 +605,18 @@ namespace System.Runtime.Intrinsics.Arm public static Vector128 Divide(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// + /// float64x2_t vfmaq_f64 (float64x2_t a, float64x2_t b, float64x2_t c) + /// A64: FMLA Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 FusedMultiplyAdd(Vector128 acc, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// float64x2_t vfmsq_f64 (float64x2_t a, float64x2_t b, float64x2_t c) + /// A64: FMLS Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 FusedMultiplySubtract(Vector128 acc, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// /// float64x2_t vmaxq_f64 (float64x2_t a, float64x2_t b) /// A64: FMAX Vd.2D, Vn.2D, Vm.2D /// @@ -1021,18 +1033,6 @@ namespace System.Runtime.Intrinsics.Arm public static Vector128 Sqrt(Vector128 value) { throw new PlatformNotSupportedException(); } /// - /// float64x2_t vfmaq_f64 (float64x2_t a, float64x2_t b, float64x2_t c) - /// A64: FMLA Vd.2D, Vn.2D, Vm.2D - /// - public static Vector128 FusedMultiplyAdd(Vector128 acc, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// - /// float64x2_t vfmsq_f64 (float64x2_t a, float64x2_t b, float64x2_t c) - /// A64: FMLS Vd.2D, Vn.2D, Vm.2D - /// - public static Vector128 FusedMultiplySubtract(Vector128 acc, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// /// float64x2_t vsubq_f64 (float64x2_t a, float64x2_t b) /// A64: FSUB Vd.2D, Vn.2D, Vm.2D /// @@ -4657,6 +4657,146 @@ namespace System.Runtime.Intrinsics.Arm public static Vector64 SqrtScalar(Vector64 value) { throw new PlatformNotSupportedException(); } /// + /// void vst1_u8 (uint8_t * ptr, uint8x8_t val) + /// A32: VST1.8 { Dd }, [Rn] + /// A64: ST1 { Vt.8B }, [Xn] + /// + public static unsafe void Store(byte* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_f64 (float64_t * ptr, float64x1_t val) + /// A32: VST1.64 { Dd }, [Rn] + /// A64: ST1 { Vt.1D }, [Xn] + /// + public static unsafe void Store(double* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_s16 (int16_t * ptr, int16x4_t val) + /// A32: VST1.16 { Dd }, [Rn] + /// A64: ST1 {Vt.4H }, [Xn] + /// + public static unsafe void Store(short* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_s32 (int32_t * ptr, int32x2_t val) + /// A32: VST1.32 { Dd }, [Rn] + /// A64: ST1 { Vt.2S }, [Xn] + /// + public static unsafe void Store(int* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_s64 (int64_t * ptr, int64x1_t val) + /// A32: VST1.64 { Dd }, [Rn] + /// A64: ST1 { Vt.1D }, [Xn] + /// + public static unsafe void Store(long* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_s8 (int8_t * ptr, int8x8_t val) + /// A32: VST1.8 { Dd }, [Rn] + /// A64: ST1 { Vt.8B }, [Xn] + /// + public static unsafe void Store(sbyte* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_f32 (float32_t * ptr, float32x2_t val) + /// A32: VST1.32 { Dd }, [Rn] + /// A64: ST1 { Vt.2S }, [Xn] + /// + public static unsafe void Store(float* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_u16 (uint16_t * ptr, uint16x4_t val) + /// A32: VST1.16 { Dd }, [Rn] + /// A64: ST1 { Vt.4H }, [Xn] + /// + public static unsafe void Store(ushort* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_u32 (uint32_t * ptr, uint32x2_t val) + /// A32: VST1.32 { Dd }, [Rn] + /// A64: ST1 { Vt.2S }, [Xn] + /// + public static unsafe void Store(uint* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_u64 (uint64_t * ptr, uint64x1_t val) + /// A32: VST1.64 { Dd }, [Rn] + /// A64: ST1 { Vt.1D }, [Xn] + /// + public static unsafe void Store(ulong* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1q_u8 (uint8_t * ptr, uint8x16_t val) + /// A32: VST1.8 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.16B }, [Xn] + /// + public static unsafe void Store(byte* address, Vector128 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1q_f64 (float64_t * ptr, float64x2_t val) + /// A32: VST1.64 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.2D }, [Xn] + /// + public static unsafe void Store(double* address, Vector128 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1q_s16 (int16_t * ptr, int16x8_t val) + /// A32: VST1.16 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.8H }, [Xn] + /// + public static unsafe void Store(short* address, Vector128 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1q_s32 (int32_t * ptr, int32x4_t val) + /// A32: VST1.32 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.4S }, [Xn] + /// + public static unsafe void Store(int* address, Vector128 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1q_s64 (int64_t * ptr, int64x2_t val) + /// A32: VST1.64 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.2D }, [Xn] + /// + public static unsafe void Store(long* address, Vector128 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1q_s8 (int8_t * ptr, int8x16_t val) + /// A32: VST1.8 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.16B }, [Xn] + /// + public static unsafe void Store(sbyte* address, Vector128 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1q_f32 (float32_t * ptr, float32x4_t val) + /// A32: VST1.32 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.4S }, [Xn] + /// + public static unsafe void Store(float* address, Vector128 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1q_u16 (uint16_t * ptr, uint16x8_t val) + /// A32: VST1.16 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.8H }, [Xn] + /// + public static unsafe void Store(ushort* address, Vector128 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1q_u32 (uint32_t * ptr, uint32x4_t val) + /// A32: VST1.32 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.4S }, [Xn] + /// + public static unsafe void Store(uint* address, Vector128 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1q_u64 (uint64_t * ptr, uint64x2_t val) + /// A32: VST1.64 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.2D }, [Xn] + /// + public static unsafe void Store(ulong* address, Vector128 source) { throw new PlatformNotSupportedException(); } + + /// /// uint8x8_t vsub_u8 (uint8x8_t a, uint8x8_t b) /// A32: VSUB.I8 Dd, Dn, Dm /// A64: SUB Vd.8B, Vn.8B, Vm.8B 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 112dc1e..c000c31 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 @@ -607,6 +607,18 @@ namespace System.Runtime.Intrinsics.Arm public static Vector128 Divide(Vector128 left, Vector128 right) => Divide(left, right); /// + /// float64x2_t vfmaq_f64 (float64x2_t a, float64x2_t b, float64x2_t c) + /// A64: FMLA Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 FusedMultiplyAdd(Vector128 acc, Vector128 left, Vector128 right) => FusedMultiplyAdd(acc, left, right); + + /// + /// float64x2_t vfmsq_f64 (float64x2_t a, float64x2_t b, float64x2_t c) + /// A64: FMLS Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 FusedMultiplySubtract(Vector128 acc, Vector128 left, Vector128 right) => FusedMultiplySubtract(acc, left, right); + + /// /// float64x2_t vmaxq_f64 (float64x2_t a, float64x2_t b) /// A64: FMAX Vd.2D, Vn.2D, Vm.2D /// @@ -1023,18 +1035,6 @@ namespace System.Runtime.Intrinsics.Arm public static Vector128 Sqrt(Vector128 value) => Sqrt(value); /// - /// float64x2_t vfmaq_f64 (float64x2_t a, float64x2_t b, float64x2_t c) - /// A64: FMLA Vd.2D, Vn.2D, Vm.2D - /// - public static Vector128 FusedMultiplyAdd(Vector128 acc, Vector128 left, Vector128 right) => FusedMultiplyAdd(acc, left, right); - - /// - /// float64x2_t vfmsq_f64 (float64x2_t a, float64x2_t b, float64x2_t c) - /// A64: FMLS Vd.2D, Vn.2D, Vm.2D - /// - public static Vector128 FusedMultiplySubtract(Vector128 acc, Vector128 left, Vector128 right) => FusedMultiplySubtract(acc, left, right); - - /// /// float64x2_t vsubq_f64 (float64x2_t a, float64x2_t b) /// A64: FSUB Vd.2D, Vn.2D, Vm.2D /// @@ -4659,6 +4659,146 @@ namespace System.Runtime.Intrinsics.Arm public static Vector64 SqrtScalar(Vector64 value) => SqrtScalar(value); /// + /// void vst1_u8 (uint8_t * ptr, uint8x8_t val) + /// A32: VST1.8 { Dd }, [Rn] + /// A64: ST1 { Vt.8B }, [Xn] + /// + public static unsafe void Store(byte* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_f64 (float64_t * ptr, float64x1_t val) + /// A32: VST1.64 { Dd }, [Rn] + /// A64: ST1 { Vt.1D }, [Xn] + /// + public static unsafe void Store(double* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_s16 (int16_t * ptr, int16x4_t val) + /// A32: VST1.16 { Dd }, [Rn] + /// A64: ST1 {Vt.4H }, [Xn] + /// + public static unsafe void Store(short* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_s32 (int32_t * ptr, int32x2_t val) + /// A32: VST1.32 { Dd }, [Rn] + /// A64: ST1 { Vt.2S }, [Xn] + /// + public static unsafe void Store(int* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_s64 (int64_t * ptr, int64x1_t val) + /// A32: VST1.64 { Dd }, [Rn] + /// A64: ST1 { Vt.1D }, [Xn] + /// + public static unsafe void Store(long* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_s8 (int8_t * ptr, int8x8_t val) + /// A32: VST1.8 { Dd }, [Rn] + /// A64: ST1 { Vt.8B }, [Xn] + /// + public static unsafe void Store(sbyte* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_f32 (float32_t * ptr, float32x2_t val) + /// A32: VST1.32 { Dd }, [Rn] + /// A64: ST1 { Vt.2S }, [Xn] + /// + public static unsafe void Store(float* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_u16 (uint16_t * ptr, uint16x4_t val) + /// A32: VST1.16 { Dd }, [Rn] + /// A64: ST1 { Vt.4H }, [Xn] + /// + public static unsafe void Store(ushort* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_u32 (uint32_t * ptr, uint32x2_t val) + /// A32: VST1.32 { Dd }, [Rn] + /// A64: ST1 { Vt.2S }, [Xn] + /// + public static unsafe void Store(uint* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_u64 (uint64_t * ptr, uint64x1_t val) + /// A32: VST1.64 { Dd }, [Rn] + /// A64: ST1 { Vt.1D }, [Xn] + /// + public static unsafe void Store(ulong* address, Vector64 source) => Store(address, source); + + /// + /// void vst1q_u8 (uint8_t * ptr, uint8x16_t val) + /// A32: VST1.8 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.16B }, [Xn] + /// + public static unsafe void Store(byte* address, Vector128 source) => Store(address, source); + + /// + /// void vst1q_f64 (float64_t * ptr, float64x2_t val) + /// A32: VST1.64 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.2D }, [Xn] + /// + public static unsafe void Store(double* address, Vector128 source) => Store(address, source); + + /// + /// void vst1q_s16 (int16_t * ptr, int16x8_t val) + /// A32: VST1.16 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.8H }, [Xn] + /// + public static unsafe void Store(short* address, Vector128 source) => Store(address, source); + + /// + /// void vst1q_s32 (int32_t * ptr, int32x4_t val) + /// A32: VST1.32 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.4S }, [Xn] + /// + public static unsafe void Store(int* address, Vector128 source) => Store(address, source); + + /// + /// void vst1q_s64 (int64_t * ptr, int64x2_t val) + /// A32: VST1.64 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.2D }, [Xn] + /// + public static unsafe void Store(long* address, Vector128 source) => Store(address, source); + + /// + /// void vst1q_s8 (int8_t * ptr, int8x16_t val) + /// A32: VST1.8 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.16B }, [Xn] + /// + public static unsafe void Store(sbyte* address, Vector128 source) => Store(address, source); + + /// + /// void vst1q_f32 (float32_t * ptr, float32x4_t val) + /// A32: VST1.32 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.4S }, [Xn] + /// + public static unsafe void Store(float* address, Vector128 source) => Store(address, source); + + /// + /// void vst1q_u16 (uint16_t * ptr, uint16x8_t val) + /// A32: VST1.16 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.8H }, [Xn] + /// + public static unsafe void Store(ushort* address, Vector128 source) => Store(address, source); + + /// + /// void vst1q_u32 (uint32_t * ptr, uint32x4_t val) + /// A32: VST1.32 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.4S }, [Xn] + /// + public static unsafe void Store(uint* address, Vector128 source) => Store(address, source); + + /// + /// void vst1q_u64 (uint64_t * ptr, uint64x2_t val) + /// A32: VST1.64 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.2D }, [Xn] + /// + public static unsafe void Store(ulong* address, Vector128 source) => Store(address, source); + + /// /// uint8x8_t vsub_u8 (uint8x8_t a, uint8x8_t b) /// A32: VSUB.I8 Dd, Dn, Dm /// A64: SUB Vd.8B, Vn.8B, Vm.8B diff --git a/src/libraries/System.Runtime.Intrinsics.Experimental/ref/System.Runtime.Intrinsics.Experimental.cs b/src/libraries/System.Runtime.Intrinsics.Experimental/ref/System.Runtime.Intrinsics.Experimental.cs index 16f106b..5dfad90 100644 --- a/src/libraries/System.Runtime.Intrinsics.Experimental/ref/System.Runtime.Intrinsics.Experimental.cs +++ b/src/libraries/System.Runtime.Intrinsics.Experimental/ref/System.Runtime.Intrinsics.Experimental.cs @@ -433,6 +433,26 @@ namespace System.Runtime.Intrinsics.Arm public static System.Runtime.Intrinsics.Vector64 PopCount(System.Runtime.Intrinsics.Vector64 value) { throw null; } public static System.Runtime.Intrinsics.Vector64 SqrtScalar(System.Runtime.Intrinsics.Vector64 value) { throw null; } public static System.Runtime.Intrinsics.Vector64 SqrtScalar(System.Runtime.Intrinsics.Vector64 value) { throw null; } + public unsafe static void Store(byte* address, System.Runtime.Intrinsics.Vector128 source) { } + public unsafe static void Store(byte* address, System.Runtime.Intrinsics.Vector64 source) { } + public unsafe static void Store(double* address, System.Runtime.Intrinsics.Vector128 source) { } + public unsafe static void Store(double* address, System.Runtime.Intrinsics.Vector64 source) { } + public unsafe static void Store(short* address, System.Runtime.Intrinsics.Vector128 source) { } + public unsafe static void Store(short* address, System.Runtime.Intrinsics.Vector64 source) { } + public unsafe static void Store(int* address, System.Runtime.Intrinsics.Vector128 source) { } + public unsafe static void Store(int* address, System.Runtime.Intrinsics.Vector64 source) { } + public unsafe static void Store(long* address, System.Runtime.Intrinsics.Vector128 source) { } + public unsafe static void Store(long* address, System.Runtime.Intrinsics.Vector64 source) { } + public unsafe static void Store(sbyte* address, System.Runtime.Intrinsics.Vector128 source) { } + public unsafe static void Store(sbyte* address, System.Runtime.Intrinsics.Vector64 source) { } + public unsafe static void Store(float* address, System.Runtime.Intrinsics.Vector128 source) { } + public unsafe static void Store(float* address, System.Runtime.Intrinsics.Vector64 source) { } + public unsafe static void Store(ushort* address, System.Runtime.Intrinsics.Vector128 source) { } + public unsafe static void Store(ushort* address, System.Runtime.Intrinsics.Vector64 source) { } + public unsafe static void Store(uint* address, System.Runtime.Intrinsics.Vector128 source) { } + public unsafe static void Store(uint* address, System.Runtime.Intrinsics.Vector64 source) { } + public unsafe static void Store(ulong* address, System.Runtime.Intrinsics.Vector128 source) { } + public unsafe static void Store(ulong* address, System.Runtime.Intrinsics.Vector64 source) { } public static System.Runtime.Intrinsics.Vector128 Subtract(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 Subtract(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 Subtract(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } -- 2.7.4