From 3fcae9ad81ca620bf0e52272430e4f65d35a5e52 Mon Sep 17 00:00:00 2001 From: Tamar Christina Date: Thu, 11 Jun 2020 12:52:29 +0100 Subject: [PATCH] Arm64: Implement shift and insert intrinsics --- src/coreclr/src/jit/hwintrinsic.h | 2 +- src/coreclr/src/jit/hwintrinsicarm64.cpp | 4 + .../src/jit/hwintrinsiccodegenarm64.cpp | 12 + src/coreclr/src/jit/hwintrinsiclistarm64.h | 4 + src/coreclr/src/jit/lowerarmarch.cpp | 4 + src/coreclr/src/jit/lsraarm64.cpp | 4 + .../Arm/AdvSimd/AdvSimd_r.csproj | 32 + .../Arm/AdvSimd/AdvSimd_ro.csproj | 32 + .../Arm/AdvSimd/Program.AdvSimd.cs | 32 + ...hiftLeftLogicalAndInsert.Vector128.Byte.cs | 550 ++++++++++++++++++ ...iftLeftLogicalAndInsert.Vector128.Int16.cs | 550 ++++++++++++++++++ ...iftLeftLogicalAndInsert.Vector128.Int32.cs | 550 ++++++++++++++++++ ...iftLeftLogicalAndInsert.Vector128.Int64.cs | 550 ++++++++++++++++++ ...iftLeftLogicalAndInsert.Vector128.SByte.cs | 550 ++++++++++++++++++ ...ftLeftLogicalAndInsert.Vector128.UInt16.cs | 550 ++++++++++++++++++ ...ftLeftLogicalAndInsert.Vector128.UInt32.cs | 550 ++++++++++++++++++ ...ftLeftLogicalAndInsert.Vector128.UInt64.cs | 550 ++++++++++++++++++ ...ShiftLeftLogicalAndInsert.Vector64.Byte.cs | 550 ++++++++++++++++++ ...hiftLeftLogicalAndInsert.Vector64.Int16.cs | 550 ++++++++++++++++++ ...hiftLeftLogicalAndInsert.Vector64.Int32.cs | 550 ++++++++++++++++++ ...hiftLeftLogicalAndInsert.Vector64.SByte.cs | 550 ++++++++++++++++++ ...iftLeftLogicalAndInsert.Vector64.UInt16.cs | 550 ++++++++++++++++++ ...iftLeftLogicalAndInsert.Vector64.UInt32.cs | 550 ++++++++++++++++++ ...ftLogicalAndInsertScalar.Vector64.Int64.cs | 550 ++++++++++++++++++ ...tLogicalAndInsertScalar.Vector64.UInt64.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector128.Byte.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector128.Int16.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector128.Int32.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector128.Int64.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector128.SByte.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector128.UInt16.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector128.UInt32.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector128.UInt64.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector64.Byte.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector64.Int16.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector64.Int32.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector64.SByte.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector64.UInt16.cs | 550 ++++++++++++++++++ .../ShiftRightAndInsert.Vector64.UInt32.cs | 550 ++++++++++++++++++ ...htLogicalAndInsertScalar.Vector64.Int64.cs | 550 ++++++++++++++++++ ...tLogicalAndInsertScalar.Vector64.UInt64.cs | 550 ++++++++++++++++++ .../Arm/Shared/GenerateTests.csx | 33 ++ .../HardwareIntrinsics/Arm/Shared/Helpers.cs | 146 ++++- .../HardwareIntrinsics/Arm/Shared/Helpers.tt | 37 +- .../Shared/_ImmTernaryOpTestTemplate.template | 543 +++++++++++++++++ .../Arm/AdvSimd.PlatformNotSupported.cs | 224 +++++++ .../System/Runtime/Intrinsics/Arm/AdvSimd.cs | 224 +++++++ .../ref/System.Runtime.Intrinsics.cs | 32 + 48 files changed, 18957 insertions(+), 8 deletions(-) create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.Byte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.Int16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.Int32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.Int64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.SByte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.UInt16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.UInt32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.UInt64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.Byte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.Int16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.Int32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.SByte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.UInt16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.UInt32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsertScalar.Vector64.Int64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsertScalar.Vector64.UInt64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.Byte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.Int16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.Int32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.Int64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.SByte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.UInt16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.UInt32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.UInt64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.Byte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.Int16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.Int32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.SByte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.UInt16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.UInt32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAndInsertScalar.Vector64.Int64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAndInsertScalar.Vector64.UInt64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_ImmTernaryOpTestTemplate.template diff --git a/src/coreclr/src/jit/hwintrinsic.h b/src/coreclr/src/jit/hwintrinsic.h index 34a92d858e43dc..3a53e24d3e635f 100644 --- a/src/coreclr/src/jit/hwintrinsic.h +++ b/src/coreclr/src/jit/hwintrinsic.h @@ -104,7 +104,7 @@ enum HWIntrinsicFlag : unsigned int HW_Flag_NoRMWSemantics = 0x4000, // NoContainment - // the intrinsic cannot be handled by comtainment, + // the intrinsic cannot be handled by containment, // all the intrinsic that have explicit memory load/store semantics should have this flag HW_Flag_NoContainment = 0x8000, diff --git a/src/coreclr/src/jit/hwintrinsicarm64.cpp b/src/coreclr/src/jit/hwintrinsicarm64.cpp index 504bd0c621b81c..030d23aaacaf4c 100644 --- a/src/coreclr/src/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/src/jit/hwintrinsicarm64.cpp @@ -218,6 +218,8 @@ void HWIntrinsicInfo::lookupImmBounds( break; case NI_AdvSimd_ShiftLeftLogical: + case NI_AdvSimd_ShiftLeftLogicalAndInsert: + case NI_AdvSimd_ShiftLeftLogicalAndInsertScalar: case NI_AdvSimd_ShiftLeftLogicalSaturate: case NI_AdvSimd_ShiftLeftLogicalSaturateScalar: case NI_AdvSimd_ShiftLeftLogicalSaturateUnsigned: @@ -231,6 +233,7 @@ void HWIntrinsicInfo::lookupImmBounds( immUpperBound = BITS_PER_BYTE * genTypeSize(baseType) - 1; break; + case NI_AdvSimd_ShiftRightAndInsert: case NI_AdvSimd_ShiftRightArithmetic: case NI_AdvSimd_ShiftRightArithmeticAdd: case NI_AdvSimd_ShiftRightArithmeticAddScalar: @@ -250,6 +253,7 @@ void HWIntrinsicInfo::lookupImmBounds( case NI_AdvSimd_ShiftRightLogical: case NI_AdvSimd_ShiftRightLogicalAdd: case NI_AdvSimd_ShiftRightLogicalAddScalar: + case NI_AdvSimd_ShiftRightLogicalAndInsertScalar: case NI_AdvSimd_ShiftRightLogicalNarrowingLower: case NI_AdvSimd_ShiftRightLogicalNarrowingSaturateLower: case NI_AdvSimd_ShiftRightLogicalNarrowingSaturateUpper: diff --git a/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp index 179c1807e118a1..5c337642db553b 100644 --- a/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp @@ -333,6 +333,14 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) } break; + case NI_AdvSimd_ShiftLeftLogicalAndInsertScalar: + ins = INS_sli; + break; + + case NI_AdvSimd_ShiftRightLogicalAndInsertScalar: + ins = INS_sri; + break; + case NI_AdvSimd_SubtractWideningLower: assert(varTypeIsIntegral(intrin.baseType)); if (intrin.op1->TypeGet() == TYP_SIMD8) @@ -716,9 +724,11 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) } break; + case NI_AdvSimd_ShiftLeftLogicalAndInsertScalar: case NI_AdvSimd_ShiftRightArithmeticAddScalar: case NI_AdvSimd_ShiftRightArithmeticRoundedAddScalar: case NI_AdvSimd_ShiftRightLogicalAddScalar: + case NI_AdvSimd_ShiftRightLogicalAndInsertScalar: case NI_AdvSimd_ShiftRightLogicalRoundedAddScalar: opt = INS_OPTS_NONE; emitSize = emitTypeSize(intrin.baseType); @@ -736,6 +746,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) case NI_AdvSimd_ShiftRightLogicalRoundedAdd: case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingSaturateUpper: case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingUpper: + case NI_AdvSimd_ShiftLeftLogicalAndInsert: + case NI_AdvSimd_ShiftRightAndInsert: { assert(isRMW); diff --git a/src/coreclr/src/jit/hwintrinsiclistarm64.h b/src/coreclr/src/jit/hwintrinsiclistarm64.h index 553be2ff1e665c..7c82d47e7d172e 100644 --- a/src/coreclr/src/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/src/jit/hwintrinsiclistarm64.h @@ -179,6 +179,8 @@ HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticSaturate, HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogical, -1, 2, {INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalAndInsert, -1, 3, {INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalAndInsertScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sli, INS_sli, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturate, -1, 2, {INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturateUnsigned, -1, 2, {INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) @@ -194,6 +196,8 @@ HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalRoundedScalar, HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalSaturate, -1, 2, {INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_uqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ushl, INS_ushl, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightAndInsert, -1, 3, {INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalAndInsertScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sri, INS_sri, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmetic, -1, 2, {INS_sshr, INS_invalid, INS_sshr, INS_invalid, INS_sshr, INS_invalid, INS_sshr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticAdd, -1, 3, {INS_ssra, INS_invalid, INS_ssra, INS_invalid, INS_ssra, INS_invalid, INS_ssra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticAddScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ssra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) diff --git a/src/coreclr/src/jit/lowerarmarch.cpp b/src/coreclr/src/jit/lowerarmarch.cpp index c3ac6513e9546c..3b485fadd56703 100644 --- a/src/coreclr/src/jit/lowerarmarch.cpp +++ b/src/coreclr/src/jit/lowerarmarch.cpp @@ -1426,6 +1426,9 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_AdvSimd_ExtractVector64: case NI_AdvSimd_ExtractVector128: + case NI_AdvSimd_ShiftLeftLogicalAndInsert: + case NI_AdvSimd_ShiftLeftLogicalAndInsertScalar: + case NI_AdvSimd_ShiftRightAndInsert: case NI_AdvSimd_ShiftRightArithmeticAdd: case NI_AdvSimd_ShiftRightArithmeticAddScalar: case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUnsignedUpper: @@ -1436,6 +1439,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUpper: case NI_AdvSimd_ShiftRightLogicalAdd: case NI_AdvSimd_ShiftRightLogicalAddScalar: + case NI_AdvSimd_ShiftRightLogicalAndInsertScalar: case NI_AdvSimd_ShiftRightLogicalNarrowingSaturateUpper: case NI_AdvSimd_ShiftRightLogicalNarrowingUpper: case NI_AdvSimd_ShiftRightLogicalRoundedAdd: diff --git a/src/coreclr/src/jit/lsraarm64.cpp b/src/coreclr/src/jit/lsraarm64.cpp index c7146d6872af02..4c2fa39a4957bf 100644 --- a/src/coreclr/src/jit/lsraarm64.cpp +++ b/src/coreclr/src/jit/lsraarm64.cpp @@ -1050,6 +1050,9 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) case NI_AdvSimd_ExtractVector64: case NI_AdvSimd_ExtractVector128: + case NI_AdvSimd_ShiftLeftLogicalAndInsert: + case NI_AdvSimd_ShiftLeftLogicalAndInsertScalar: + case NI_AdvSimd_ShiftRightAndInsert: case NI_AdvSimd_ShiftRightArithmeticAdd: case NI_AdvSimd_ShiftRightArithmeticAddScalar: case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUnsignedUpper: @@ -1060,6 +1063,7 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUpper: case NI_AdvSimd_ShiftRightLogicalAdd: case NI_AdvSimd_ShiftRightLogicalAddScalar: + case NI_AdvSimd_ShiftRightLogicalAndInsertScalar: case NI_AdvSimd_ShiftRightLogicalNarrowingSaturateUpper: case NI_AdvSimd_ShiftRightLogicalNarrowingUpper: case NI_AdvSimd_ShiftRightLogicalRoundedAdd: 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 7f2d981717c87d..a239f74b22f141 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 @@ -752,6 +752,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 a6abd34f4f1ea6..1763ba46475d24 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 @@ -752,6 +752,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 636a26238b5648..42c1b1fa5e9ef4 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 @@ -756,6 +756,38 @@ static Program() ["PopCount.Vector128.SByte"] = PopCount_Vector128_SByte, ["ReciprocalEstimate.Vector64.Single"] = ReciprocalEstimate_Vector64_Single, ["ReciprocalEstimate.Vector64.UInt32"] = ReciprocalEstimate_Vector64_UInt32, + ["ShiftLeftLogicalAndInsert.Vector64.Byte"] = ShiftLeftLogicalAndInsert_Vector64_Byte, + ["ShiftLeftLogicalAndInsert.Vector64.Int16"] = ShiftLeftLogicalAndInsert_Vector64_Int16, + ["ShiftLeftLogicalAndInsert.Vector64.Int32"] = ShiftLeftLogicalAndInsert_Vector64_Int32, + ["ShiftLeftLogicalAndInsert.Vector64.SByte"] = ShiftLeftLogicalAndInsert_Vector64_SByte, + ["ShiftLeftLogicalAndInsert.Vector64.UInt16"] = ShiftLeftLogicalAndInsert_Vector64_UInt16, + ["ShiftLeftLogicalAndInsert.Vector64.UInt32"] = ShiftLeftLogicalAndInsert_Vector64_UInt32, + ["ShiftLeftLogicalAndInsert.Vector128.Byte"] = ShiftLeftLogicalAndInsert_Vector128_Byte, + ["ShiftLeftLogicalAndInsert.Vector128.Int16"] = ShiftLeftLogicalAndInsert_Vector128_Int16, + ["ShiftLeftLogicalAndInsert.Vector128.Int32"] = ShiftLeftLogicalAndInsert_Vector128_Int32, + ["ShiftLeftLogicalAndInsert.Vector128.Int64"] = ShiftLeftLogicalAndInsert_Vector128_Int64, + ["ShiftLeftLogicalAndInsert.Vector128.SByte"] = ShiftLeftLogicalAndInsert_Vector128_SByte, + ["ShiftLeftLogicalAndInsert.Vector128.UInt16"] = ShiftLeftLogicalAndInsert_Vector128_UInt16, + ["ShiftLeftLogicalAndInsert.Vector128.UInt32"] = ShiftLeftLogicalAndInsert_Vector128_UInt32, + ["ShiftLeftLogicalAndInsert.Vector128.UInt64"] = ShiftLeftLogicalAndInsert_Vector128_UInt64, + ["ShiftLeftLogicalAndInsertScalar.Vector64.Int64"] = ShiftLeftLogicalAndInsertScalar_Vector64_Int64, + ["ShiftLeftLogicalAndInsertScalar.Vector64.UInt64"] = ShiftLeftLogicalAndInsertScalar_Vector64_UInt64, + ["ShiftRightAndInsert.Vector64.Byte"] = ShiftRightAndInsert_Vector64_Byte, + ["ShiftRightAndInsert.Vector64.Int16"] = ShiftRightAndInsert_Vector64_Int16, + ["ShiftRightAndInsert.Vector64.Int32"] = ShiftRightAndInsert_Vector64_Int32, + ["ShiftRightAndInsert.Vector64.SByte"] = ShiftRightAndInsert_Vector64_SByte, + ["ShiftRightAndInsert.Vector64.UInt16"] = ShiftRightAndInsert_Vector64_UInt16, + ["ShiftRightAndInsert.Vector64.UInt32"] = ShiftRightAndInsert_Vector64_UInt32, + ["ShiftRightAndInsert.Vector128.Byte"] = ShiftRightAndInsert_Vector128_Byte, + ["ShiftRightAndInsert.Vector128.Int16"] = ShiftRightAndInsert_Vector128_Int16, + ["ShiftRightAndInsert.Vector128.Int32"] = ShiftRightAndInsert_Vector128_Int32, + ["ShiftRightAndInsert.Vector128.Int64"] = ShiftRightAndInsert_Vector128_Int64, + ["ShiftRightAndInsert.Vector128.SByte"] = ShiftRightAndInsert_Vector128_SByte, + ["ShiftRightAndInsert.Vector128.UInt16"] = ShiftRightAndInsert_Vector128_UInt16, + ["ShiftRightAndInsert.Vector128.UInt32"] = ShiftRightAndInsert_Vector128_UInt32, + ["ShiftRightAndInsert.Vector128.UInt64"] = ShiftRightAndInsert_Vector128_UInt64, + ["ShiftRightLogicalAndInsertScalar.Vector64.Int64"] = ShiftRightLogicalAndInsertScalar_Vector64_Int64, + ["ShiftRightLogicalAndInsertScalar.Vector64.UInt64"] = ShiftRightLogicalAndInsertScalar_Vector64_UInt64, ["ReciprocalEstimate.Vector128.Single"] = ReciprocalEstimate_Vector128_Single, ["ReciprocalEstimate.Vector128.UInt32"] = ReciprocalEstimate_Vector128_UInt32, ["ReciprocalSquareRootEstimate.Vector64.Single"] = ReciprocalSquareRootEstimate_Vector64_Single, diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.Byte.cs new file mode 100644 index 00000000000000..6a94204512e310 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.Byte.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector128_Byte() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Byte[] inArray2, Byte immValue, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Byte testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Byte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((Byte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + _fldImm = Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Byte*)(pClsVar1)), + AdvSimd.LoadVector128((Byte*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Byte(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Byte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((Byte*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((Byte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Byte*)(&test._fld1)), + AdvSimd.LoadVector128((Byte*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Byte[] left, Byte[] right, Byte imm, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsert.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.Int16.cs new file mode 100644 index 00000000000000..4e5645546f1c8c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.Int16.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector128_Int16() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Byte immValue, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int16 testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _fldImm = Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int16(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Byte imm, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsert.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.Int32.cs new file mode 100644 index 00000000000000..689135ebafc09c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.Int32.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector128_Int32() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Byte immValue, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int32 testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _fldImm = Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int32(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Byte imm, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsert.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.Int64.cs new file mode 100644 index 00000000000000..37e77e1bccf93e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.Int64.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector128_Int64() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Byte immValue, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int64 testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _fldImm = Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int64(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_Int64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((Int64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Byte imm, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsert.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.SByte.cs new file mode 100644 index 00000000000000..295ae4010a343a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.SByte.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector128_SByte() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, Byte immValue, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_SByte testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _fldImm = Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((SByte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_SByte(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((SByte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, Byte imm, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsert.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.UInt16.cs new file mode 100644 index 00000000000000..805119d64aa69c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.UInt16.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector128_UInt16() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt16[] inArray2, Byte immValue, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt16 testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((UInt16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _fldImm = Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt16*)(pClsVar1)), + AdvSimd.LoadVector128((UInt16*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt16(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((UInt16*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((UInt16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt16*)(&test._fld1)), + AdvSimd.LoadVector128((UInt16*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(UInt16[] left, UInt16[] right, Byte imm, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsert.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.UInt32.cs new file mode 100644 index 00000000000000..aa2261cd0f3dc7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.UInt32.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector128_UInt32() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt32[] inArray2, Byte immValue, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt32 testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((UInt32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _fldImm = Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt32*)(pClsVar1)), + AdvSimd.LoadVector128((UInt32*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt32(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((UInt32*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((UInt32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt32*)(&test._fld1)), + AdvSimd.LoadVector128((UInt32*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(UInt32[] left, UInt32[] right, Byte imm, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsert.Vector128.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.UInt64.cs new file mode 100644 index 00000000000000..1b139cde1988a3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector128.UInt64.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector128_UInt64() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, UInt64[] inArray2, Byte immValue, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt64 testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((UInt64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _fldImm = Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt64*)(pClsVar1)), + AdvSimd.LoadVector128((UInt64*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt64(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector128_UInt64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((UInt64*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((UInt64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector128((UInt64*)(&test._fld1)), + AdvSimd.LoadVector128((UInt64*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(UInt64[] left, UInt64[] right, Byte imm, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsert.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.Byte.cs new file mode 100644 index 00000000000000..c2b271c4342219 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.Byte.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector64_Byte() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Byte[] inArray2, Byte immValue, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Byte testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Byte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((Byte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + _fldImm = Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Byte*)(pClsVar1)), + AdvSimd.LoadVector64((Byte*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Byte(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Byte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((Byte*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((Byte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Byte*)(&test._fld1)), + AdvSimd.LoadVector64((Byte*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Byte[] left, Byte[] right, Byte imm, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsert.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.Int16.cs new file mode 100644 index 00000000000000..34b13e1d976218 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.Int16.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector64_Int16() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Byte immValue, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Int16 testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _fldImm = Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Int16(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Byte imm, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsert.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.Int32.cs new file mode 100644 index 00000000000000..06a9c60dda68ac --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.Int32.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector64_Int32() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Byte immValue, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Int32 testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _fldImm = Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Int32(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Byte imm, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsert.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.SByte.cs new file mode 100644 index 00000000000000..662b90dfb10880 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.SByte.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector64_SByte() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, Byte immValue, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_SByte testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _fldImm = Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_SByte(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, Byte imm, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsert.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.UInt16.cs new file mode 100644 index 00000000000000..a61bf583788b78 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.UInt16.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector64_UInt16() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt16[] inArray2, Byte immValue, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_UInt16 testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_UInt16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((UInt16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _fldImm = Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((UInt16*)(pClsVar1)), + AdvSimd.LoadVector64((UInt16*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_UInt16(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_UInt16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((UInt16*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((UInt16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((UInt16*)(&test._fld1)), + AdvSimd.LoadVector64((UInt16*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(UInt16[] left, UInt16[] right, Byte imm, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsert.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.UInt32.cs new file mode 100644 index 00000000000000..2dacb4a69110cf --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsert.Vector64.UInt32.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsert_Vector64_UInt32() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt32[] inArray2, Byte immValue, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_UInt32 testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_UInt32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((UInt32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _fldImm = Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((UInt32*)(pClsVar1)), + AdvSimd.LoadVector64((UInt32*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_UInt32(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsert_Vector64_UInt32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((UInt32*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((UInt32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsert( + AdvSimd.LoadVector64((UInt32*)(&test._fld1)), + AdvSimd.LoadVector64((UInt32*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(UInt32[] left, UInt32[] right, Byte imm, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsert)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsertScalar.Vector64.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsertScalar.Vector64.Int64.cs new file mode 100644 index 00000000000000..f9166b3dfc7635 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsertScalar.Vector64.Int64.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsertScalar_Vector64_Int64() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_Vector64_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Byte immValue, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_Vector64_Int64 testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_Vector64_Int64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _fldImm = Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsertScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsertScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_Vector64_Int64(); + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_Vector64_Int64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Byte imm, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsertScalar)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftLeftLogicalAndInsertScalar.Vector64.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsertScalar.Vector64.UInt64.cs new file mode 100644 index 00000000000000..71ac4d08162b74 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalAndInsertScalar.Vector64.UInt64.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftLeftLogicalAndInsertScalar_Vector64_UInt64() + { + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_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 ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_Vector64_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, UInt64[] inArray2, Byte immValue, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), false); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_Vector64_UInt64 testClass) + { + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_Vector64_UInt64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((UInt64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), false); + } + + public ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _fldImm = Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), false); + _dataTable = new DataTable(_data1, _data2, _fldImm, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsertScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalAndInsertScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + AdvSimd.LoadVector64((UInt64*)(pClsVar1)), + AdvSimd.LoadVector64((UInt64*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_Vector64_UInt64(); + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftLeftLogicalAndInsertScalar_Vector64_UInt64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((UInt64*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((UInt64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalAndInsertScalar( + AdvSimd.LoadVector64((UInt64*)(&test._fld1)), + AdvSimd.LoadVector64((UInt64*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(UInt64[] left, UInt64[] right, Byte imm, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalAndInsertScalar)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.Byte.cs new file mode 100644 index 00000000000000..5d2f52cc8a3256 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.Byte.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector128_Byte() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Byte[] inArray2, Byte immValue, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Byte testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Byte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((Byte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + _fldImm = Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Byte*)(pClsVar1)), + AdvSimd.LoadVector128((Byte*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Byte(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Byte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((Byte*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((Byte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Byte*)(&test._fld1)), + AdvSimd.LoadVector128((Byte*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Byte[] left, Byte[] right, Byte imm, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.Int16.cs new file mode 100644 index 00000000000000..8e3cd38dd038e8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.Int16.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector128_Int16() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Byte immValue, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int16 testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _fldImm = Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int16(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Byte imm, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.Int32.cs new file mode 100644 index 00000000000000..b29afef61ca81f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.Int32.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector128_Int32() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Byte immValue, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int32 testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _fldImm = Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int32(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Byte imm, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.Int64.cs new file mode 100644 index 00000000000000..6616c8ec85b5e9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.Int64.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector128_Int64() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Byte immValue, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int64 testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _fldImm = Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int64(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_Int64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((Int64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Byte imm, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.SByte.cs new file mode 100644 index 00000000000000..0289e6c1d64b67 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.SByte.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector128_SByte() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, Byte immValue, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_SByte testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _fldImm = Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((SByte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_SByte(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((SByte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, Byte imm, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.UInt16.cs new file mode 100644 index 00000000000000..07f555ff3bf3e3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.UInt16.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector128_UInt16() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt16[] inArray2, Byte immValue, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt16 testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((UInt16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _fldImm = Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt16*)(pClsVar1)), + AdvSimd.LoadVector128((UInt16*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt16(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((UInt16*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((UInt16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt16*)(&test._fld1)), + AdvSimd.LoadVector128((UInt16*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(UInt16[] left, UInt16[] right, Byte imm, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.UInt32.cs new file mode 100644 index 00000000000000..9f93ed893ec702 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.UInt32.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector128_UInt32() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt32[] inArray2, Byte immValue, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt32 testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((UInt32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _fldImm = Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt32*)(pClsVar1)), + AdvSimd.LoadVector128((UInt32*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt32(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((UInt32*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((UInt32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt32*)(&test._fld1)), + AdvSimd.LoadVector128((UInt32*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(UInt32[] left, UInt32[] right, Byte imm, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector128.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.UInt64.cs new file mode 100644 index 00000000000000..5b83ade793da0d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector128.UInt64.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector128_UInt64() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, UInt64[] inArray2, Byte immValue, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt64 testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((UInt64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + private static Byte _clsImm; + + private Vector128 _fld1; + private Vector128 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _fldImm = Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector128), typeof(Vector128), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt64*)(pClsVar1)), + AdvSimd.LoadVector128((UInt64*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt64(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector128_UInt64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((UInt64*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((UInt64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector128((UInt64*)(&test._fld1)), + AdvSimd.LoadVector128((UInt64*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector128 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(UInt64[] left, UInt64[] right, Byte imm, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector128, Vector128, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.Byte.cs new file mode 100644 index 00000000000000..649f958a87d18b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.Byte.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector64_Byte() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Byte[] inArray2, Byte immValue, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Byte testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Byte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((Byte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + _fldImm = Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Byte*)(pClsVar1)), + AdvSimd.LoadVector64((Byte*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Byte(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Byte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((Byte*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((Byte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Byte*)(&test._fld1)), + AdvSimd.LoadVector64((Byte*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Byte[] left, Byte[] right, Byte imm, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.Int16.cs new file mode 100644 index 00000000000000..875155d3868424 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.Int16.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector64_Int16() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Byte immValue, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Int16 testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _fldImm = Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Int16(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Byte imm, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.Int32.cs new file mode 100644 index 00000000000000..5f5ca34d81552f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.Int32.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector64_Int32() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Byte immValue, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Int32 testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _fldImm = Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Int32(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Byte imm, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.SByte.cs new file mode 100644 index 00000000000000..430d4c3b0fec98 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.SByte.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector64_SByte() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, Byte immValue, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector64_SByte testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _fldImm = Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector64_SByte(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, Byte imm, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.UInt16.cs new file mode 100644 index 00000000000000..556d738e8b5955 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.UInt16.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector64_UInt16() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector64_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt16[] inArray2, Byte immValue, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector64_UInt16 testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector64_UInt16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((UInt16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _fldImm = Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((UInt16*)(pClsVar1)), + AdvSimd.LoadVector64((UInt16*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector64_UInt16(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector64_UInt16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((UInt16*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((UInt16*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((UInt16*)(&test._fld1)), + AdvSimd.LoadVector64((UInt16*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(UInt16[] left, UInt16[] right, Byte imm, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightAndInsert.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.UInt32.cs new file mode 100644 index 00000000000000..9eda05fcf3dd7c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightAndInsert.Vector64.UInt32.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightAndInsert_Vector64_UInt32() + { + var test = new ImmTernaryOpTest__ShiftRightAndInsert_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 ImmTernaryOpTest__ShiftRightAndInsert_Vector64_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt32[] inArray2, Byte immValue, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightAndInsert_Vector64_UInt32 testClass) + { + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightAndInsert_Vector64_UInt32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((UInt32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightAndInsert_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightAndInsert_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _fldImm = Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightAndInsert( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightAndInsert), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightAndInsert( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((UInt32*)(pClsVar1)), + AdvSimd.LoadVector64((UInt32*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightAndInsert(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector64_UInt32(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightAndInsert_Vector64_UInt32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((UInt32*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightAndInsert(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((UInt32*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightAndInsert( + AdvSimd.LoadVector64((UInt32*)(&test._fld1)), + AdvSimd.LoadVector64((UInt32*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(UInt32[] left, UInt32[] right, Byte imm, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightAndInsert)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightLogicalAndInsertScalar.Vector64.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAndInsertScalar.Vector64.Int64.cs new file mode 100644 index 00000000000000..64716877aff0af --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAndInsertScalar.Vector64.Int64.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightLogicalAndInsertScalar_Vector64_Int64() + { + var test = new ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_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 ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_Vector64_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Byte immValue, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_Vector64_Int64 testClass) + { + var result = AdvSimd.ShiftRightLogicalAndInsertScalar(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_Vector64_Int64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _fldImm = Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAndInsertScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAndInsertScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAndInsertScalar(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAndInsertScalar(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_Vector64_Int64(); + var result = AdvSimd.ShiftRightLogicalAndInsertScalar(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_Vector64_Int64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAndInsertScalar(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAndInsertScalar(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Byte imm, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAndInsertScalar)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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/ShiftRightLogicalAndInsertScalar.Vector64.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAndInsertScalar.Vector64.UInt64.cs new file mode 100644 index 00000000000000..39f8a54dd73453 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAndInsertScalar.Vector64.UInt64.cs @@ -0,0 +1,550 @@ + +// 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.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 ShiftRightLogicalAndInsertScalar_Vector64_UInt64() + { + var test = new ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_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 ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_Vector64_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, UInt64[] inArray2, Byte immValue, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public Byte immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + public Byte _fldImm; + + 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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + testStruct._fldImm = Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), true); + + return testStruct; + } + + public void RunStructFldScenario(ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_Vector64_UInt64 testClass) + { + var result = AdvSimd.ShiftRightLogicalAndInsertScalar(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_Vector64_UInt64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((UInt64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + private static Byte _clsImm; + + private Vector64 _fld1; + private Vector64 _fld2; + private Byte _fldImm; + + private DataTable _dataTable; + + static ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_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>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + _clsImm = Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), true); + } + + public ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_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 < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _fldImm = Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), true); + _dataTable = new DataTable(_data1, _data2, _fldImm, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAndInsertScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAndInsertScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(Byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + AdvSimd.LoadVector64((UInt64*)(pClsVar1)), + AdvSimd.LoadVector64((UInt64*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAndInsertScalar(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAndInsertScalar(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_Vector64_UInt64(); + var result = AdvSimd.ShiftRightLogicalAndInsertScalar(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmTernaryOpTest__ShiftRightLogicalAndInsertScalar_Vector64_UInt64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((UInt64*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAndInsertScalar(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((UInt64*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAndInsertScalar(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAndInsertScalar( + AdvSimd.LoadVector64((UInt64*)(&test._fld1)), + AdvSimd.LoadVector64((UInt64*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, Vector64 op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, Byte imm, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + 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 inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(UInt64[] left, UInt64[] right, Byte imm, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAndInsertScalar)}(Vector64, Vector64, Byte): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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 50bc84cdbb5225..b222a941a27fc9 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx @@ -89,6 +89,7 @@ private static readonly (string templateFileName, string outputTemplateName, Dic ("_UnaryOpScalarTestTemplate.template", "DuplicateTest.template", new Dictionary { ["TemplateName"] = "Duplicate", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), ("_ImmUnaryOpTestTemplate.template", "ImmUnOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), ("_ImmUnaryOpTestTemplate.template", "VecImmUnOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_ImmTernaryOpTestTemplate.template", "ImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), ("_ImmOpTestTemplate.template", "ImmOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), ("_ImmBinaryOpTestTemplate.template", "ImmBinOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), ("_ImmBinaryOpTestTemplate.template", "VecImmBinOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), @@ -851,6 +852,38 @@ 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]"}), ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(result[i]) != 0x409e8000"}), ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.UnsignedRecipEstimate(firstOp[i]) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextImmValue"] = "Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextImmValue"] = "Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextImmValue"] = "Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextImmValue"] = "Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextImmValue"] = "Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextImmValue"] = "Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsert_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextImmValue"] = "Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsertScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsertScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalAndInsertScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalAndInsertScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextImmValue"] = "Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), false)", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextImmValue"] = "Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextImmValue"] = "Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextImmValue"] = "Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Byte), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Int16), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Int32), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextImmValue"] = "Helpers.Clamp(sizeof(SByte), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextImmValue"] = "Helpers.Clamp(sizeof(UInt16), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextImmValue"] = "Helpers.Clamp(sizeof(UInt32), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightAndInsert_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightAndInsert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["ImmType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextImmValue"] = "Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAndInsertScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAndInsertScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextImmValue"] = "Helpers.Clamp(sizeof(Int64), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), + ("ImmTernOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAndInsertScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAndInsertScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["ImmType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextImmValue"] = "Helpers.Clamp(sizeof(UInt64), TestLibrary.Generator.GetByte(), true)", ["ValidateIterResult"] = "Helpers.ShiftRightAndInsert(left[i], right[i], imm) != result[i]"}), ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(result[i]) != 0x409e8000"}), ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.UnsignedRecipEstimate(firstOp[i]) != result[i]"}), ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimate_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(result[i]) != 0x400e8000"}), diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs index 9dede7c81433f5..d6da0806565e86 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs @@ -1473,7 +1473,7 @@ private static sbyte HighNarrowing(short op1, bool round) public static short AddWideningUpper(short[] op1, sbyte[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); public static sbyte ExtractNarrowing(short op1) => (sbyte)op1; - + public static sbyte ExtractNarrowingUpper(sbyte[] op1, short[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); public static sbyte FusedAddHalving(sbyte op1, sbyte op2) => (sbyte)((ushort)((short)op1 + (short)op2) >> 1); @@ -1553,7 +1553,7 @@ private static short HighNarrowing(int op1, bool round) public static int AddWideningUpper(int[] op1, short[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); public static short ExtractNarrowing(int op1) => (short)op1; - + public static short ExtractNarrowingUpper(short[] op1, int[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); public static short FusedAddHalving(short op1, short op2) => (short)((uint)((int)op1 + (int)op2) >> 1); @@ -1633,7 +1633,7 @@ private static int HighNarrowing(long op1, bool round) public static long AddWideningUpper(long[] op1, int[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); public static int ExtractNarrowing(long op1) => (int)op1; - + public static int ExtractNarrowingUpper(int[] op1, long[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); public static int FusedAddHalving(int op1, int op2) => (int)((ulong)((long)op1 + (long)op2) >> 1); @@ -1713,7 +1713,7 @@ private static byte HighNarrowing(ushort op1, bool round) public static ushort AddWideningUpper(ushort[] op1, byte[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); public static byte ExtractNarrowing(ushort op1) => (byte)op1; - + public static byte ExtractNarrowingUpper(byte[] op1, ushort[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); public static byte FusedAddHalving(byte op1, byte op2) => (byte)((ushort)((ushort)op1 + (ushort)op2) >> 1); @@ -1793,7 +1793,7 @@ private static ushort HighNarrowing(uint op1, bool round) public static uint AddWideningUpper(uint[] op1, ushort[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); public static ushort ExtractNarrowing(uint op1) => (ushort)op1; - + public static ushort ExtractNarrowingUpper(ushort[] op1, uint[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); public static ushort FusedAddHalving(ushort op1, ushort op2) => (ushort)((uint)((uint)op1 + (uint)op2) >> 1); @@ -1873,7 +1873,7 @@ private static uint HighNarrowing(ulong op1, bool round) public static ulong AddWideningUpper(ulong[] op1, uint[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); public static uint ExtractNarrowing(ulong op1) => (uint)op1; - + public static uint ExtractNarrowingUpper(uint[] op1, ulong[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); public static uint FusedAddHalving(uint op1, uint op2) => (uint)((ulong)((ulong)op1 + (ulong)op2) >> 1); @@ -4637,6 +4637,13 @@ public static sbyte TableVectorLookup(int i, sbyte[] indices, params sbyte[][] t return TableVectorExtension(i, zeros, indices, table); } + + public static byte Clamp(int i, sbyte value, bool inclusive) + { + sbyte max = (sbyte)((i * 8) - (inclusive ? 0 : 1)); + sbyte min = ( sbyte)(inclusive ? 1 : 0); + return (byte)Math.Max (min, Math.Min(value % max, max)); + } public static byte TableVectorExtension(int i, byte[] defaultValues, byte[] indices, params byte[][] table) { byte[] fullTable = table.SelectMany(x => x).ToArray(); @@ -4656,5 +4663,132 @@ public static byte TableVectorLookup(int i, byte[] indices, params byte[][] tabl return TableVectorExtension(i, zeros, indices, table); } + public static byte Clamp(int i, byte value, bool inclusive) + { + byte max = (byte)((i * 8) - (inclusive ? 0 : 1)); + byte min = ( byte)(inclusive ? 1 : 0); + return (byte)Math.Max (min, Math.Min(value % max, max)); + } + public static byte ShiftRightAndInsert(byte left, byte right, byte shift) + { + byte mask = (byte)~(byte.MaxValue >> shift); + byte value = (byte)(right >> shift); + byte newval = (byte)(((byte)left & mask) | value); + return newval; + } + + public static byte ShiftLeftLogicalAndInsert(byte left, byte right, byte shift) + { + byte mask = (byte)~(byte.MaxValue << shift); + byte value = (byte)(right << shift); + byte newval = (byte)(((byte)left & mask) | value); + return newval; + } + public static short ShiftRightAndInsert(short left, short right, byte shift) + { + ushort mask = (ushort)~(ushort.MaxValue >> shift); + ushort value = (ushort)(right >> shift); + short newval = (short)(((ushort)left & mask) | value); + return newval; + } + + public static short ShiftLeftLogicalAndInsert(short left, short right, byte shift) + { + ushort mask = (ushort)~(ushort.MaxValue << shift); + ushort value = (ushort)(right << shift); + short newval = (short)(((ushort)left & mask) | value); + return newval; + } + public static int ShiftRightAndInsert(int left, int right, byte shift) + { + uint mask = (uint)~(uint.MaxValue >> shift); + uint value = (uint)(right >> shift); + int newval = (int)(((uint)left & mask) | value); + return newval; + } + + public static int ShiftLeftLogicalAndInsert(int left, int right, byte shift) + { + uint mask = (uint)~(uint.MaxValue << shift); + uint value = (uint)(right << shift); + int newval = (int)(((uint)left & mask) | value); + return newval; + } + public static long ShiftRightAndInsert(long left, long right, byte shift) + { + ulong mask = (ulong)~(ulong.MaxValue >> shift); + ulong value = (ulong)(right >> shift); + long newval = (long)(((ulong)left & mask) | value); + return newval; + } + + public static long ShiftLeftLogicalAndInsert(long left, long right, byte shift) + { + ulong mask = (ulong)~(ulong.MaxValue << shift); + ulong value = (ulong)(right << shift); + long newval = (long)(((ulong)left & mask) | value); + return newval; + } + public static sbyte ShiftRightAndInsert(sbyte left, sbyte right, byte shift) + { + byte mask = (byte)~(byte.MaxValue >> shift); + byte value = (byte)(right >> shift); + sbyte newval = (sbyte)(((byte)left & mask) | value); + return newval; + } + + public static sbyte ShiftLeftLogicalAndInsert(sbyte left, sbyte right, byte shift) + { + byte mask = (byte)~(byte.MaxValue << shift); + byte value = (byte)(right << shift); + sbyte newval = (sbyte)(((byte)left & mask) | value); + return newval; + } + public static ushort ShiftRightAndInsert(ushort left, ushort right, byte shift) + { + ushort mask = (ushort)~(ushort.MaxValue >> shift); + ushort value = (ushort)(right >> shift); + ushort newval = (ushort)(((ushort)left & mask) | value); + return newval; + } + + public static ushort ShiftLeftLogicalAndInsert(ushort left, ushort right, byte shift) + { + ushort mask = (ushort)~(ushort.MaxValue << shift); + ushort value = (ushort)(right << shift); + ushort newval = (ushort)(((ushort)left & mask) | value); + return newval; + } + public static uint ShiftRightAndInsert(uint left, uint right, byte shift) + { + uint mask = (uint)~(uint.MaxValue >> shift); + uint value = (uint)(right >> shift); + uint newval = (uint)(((uint)left & mask) | value); + return newval; + } + + public static uint ShiftLeftLogicalAndInsert(uint left, uint right, byte shift) + { + uint mask = (uint)~(uint.MaxValue << shift); + uint value = (uint)(right << shift); + uint newval = (uint)(((uint)left & mask) | value); + return newval; + } + public static ulong ShiftRightAndInsert(ulong left, ulong right, byte shift) + { + ulong mask = (ulong)~(ulong.MaxValue >> shift); + ulong value = (ulong)(right >> shift); + ulong newval = (ulong)(((ulong)left & mask) | value); + return newval; + } + + public static ulong ShiftLeftLogicalAndInsert(ulong left, ulong right, byte shift) + { + ulong mask = (ulong)~(ulong.MaxValue << shift); + ulong value = (ulong)(right << shift); + ulong newval = (ulong)(((ulong)left & mask) | value); + return newval; + } + } } diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt index 9c50cda89e5921..7821d4cae4f4e3 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt @@ -371,7 +371,7 @@ namespace JIT.HardwareIntrinsics.Arm public static <#= type.wide #> AddWideningUpper(<#= type.wide #>[] op1, <#= type.name #>[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); public static <#= type.name #> ExtractNarrowing(<#= type.wide #> op1) => (<#= type.name #>)op1; - + public static <#= type.name #> ExtractNarrowingUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); public static <#= type.name #> FusedAddHalving(<#= type.name #> op1, <#= type.name #> op2) => (<#= type.name #>)((<#= type.wideUnsigned #>)((<#= type.wide #>)op1 + (<#= type.wide #>)op2) >> 1); @@ -1239,6 +1239,41 @@ namespace JIT.HardwareIntrinsics.Arm return TableVectorExtension(i, zeros, indices, table); } + + public static byte Clamp(int i, <#= typeName #> value, bool inclusive) + { + <#= typeName #> max = (<#= typeName #>)((i * 8) - (inclusive ? 0 : 1)); + <#= typeName #> min = ( <#= typeName #>)(inclusive ? 1 : 0); + return (byte)Math.Max (min, Math.Min(value % max, max)); + } +<# + } + + foreach (var typeName in new[] { (original: "byte", unsigned: "byte"), + (original: "short", unsigned: "ushort"), + (original: "int", unsigned: "uint"), + (original: "long", unsigned: "ulong"), + (original: "sbyte", unsigned: "byte"), + (original: "ushort", unsigned: "ushort"), + (original: "uint", unsigned: "uint"), + (original: "ulong", unsigned: "ulong") }) + { +#> + public static <#= typeName.original #> ShiftRightAndInsert(<#= typeName.original #> left, <#= typeName.original #> right, byte shift) + { + <#= typeName.unsigned #> mask = (<#= typeName.unsigned #>)~(<#= typeName.unsigned #>.MaxValue >> shift); + <#= typeName.unsigned #> value = (<#= typeName.unsigned #>)(right >> shift); + <#= typeName.original #> newval = (<#= typeName.original #>)(((<#= typeName.unsigned #>)left & mask) | value); + return newval; + } + + public static <#= typeName.original #> ShiftLeftLogicalAndInsert(<#= typeName.original #> left, <#= typeName.original #> right, byte shift) + { + <#= typeName.unsigned #> mask = (<#= typeName.unsigned #>)~(<#= typeName.unsigned #>.MaxValue << shift); + <#= typeName.unsigned #> value = (<#= typeName.unsigned #>)(right << shift); + <#= typeName.original #> newval = (<#= typeName.original #>)(((<#= typeName.unsigned #>)left & mask) | value); + return newval; + } <# } #> diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_ImmTernaryOpTestTemplate.template b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_ImmTernaryOpTestTemplate.template new file mode 100644 index 00000000000000..b83b3ab0bc97c1 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_ImmTernaryOpTestTemplate.template @@ -0,0 +1,543 @@ + +// 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.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 {TemplateName}TernaryOpTest__{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 {TemplateName}TernaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op2BaseType}[] inArray2, {ImmType} immValue, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.immValue = immValue; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + public {ImmType} immValue; + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op2VectorType}<{Op2BaseType}> _fld2; + public {ImmType} _fldImm; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + testStruct._fldImm = {NextImmValue}; + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}TernaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2, _fldImm); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load({TemplateName}TernaryOpTest__{TestName} testClass) + { + fixed ({Op1VectorType}<{Op1BaseType}>* pFld1 = &_fld1) + fixed ({Op2VectorType}<{Op2BaseType}>* pFld2 = &_fld2) + { + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(pFld1)), + {LoadIsa}.Load{Op2VectorType}(({Op2BaseType}*)(pFld2)), + _fldImm + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fldImm, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + + private static {Op1VectorType}<{Op1BaseType}> _clsVar1; + private static {Op2VectorType}<{Op2BaseType}> _clsVar2; + private static {ImmType} _clsImm; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op2VectorType}<{Op2BaseType}> _fld2; + private {ImmType} _fldImm; + + private DataTable _dataTable; + + static {TemplateName}TernaryOpTest__{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}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _clsVar2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + _clsImm = {NextImmValue}; + } + + public {TemplateName}TernaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + _fldImm = {NextImmValue}; + _dataTable = new DataTable(_data1, _data2, _fldImm, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(({Op2BaseType}*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op2VectorType}<{Op2BaseType}>), typeof({ImmType}) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op2VectorType}<{Op2BaseType}>), typeof({ImmType}) }) + .Invoke(null, new object[] { + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(({Op2BaseType}*)(_dataTable.inArray2Ptr)), + _dataTable.immValue + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = {Isa}.{Method}( + _clsVar1, + _clsVar2, + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed ({Op1VectorType}<{Op1BaseType}>* pClsVar1 = &_clsVar1) + fixed ({Op2VectorType}<{Op2BaseType}>* pClsVar2 = &_clsVar2) + { + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(pClsVar1)), + {LoadIsa}.Load{Op2VectorType}(({Op2BaseType}*)(pClsVar2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var result = {Isa}.{Method}(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArray1Ptr)); + var op2 = {LoadIsa}.Load{Op2VectorType}(({Op2BaseType}*)(_dataTable.inArray2Ptr)); + var result = {Isa}.{Method}(op1, op2, _dataTable.immValue); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.immValue, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new {TemplateName}TernaryOpTest__{TestName}(); + var result = {Isa}.{Method}(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new {TemplateName}TernaryOpTest__{TestName}(); + + fixed ({Op1VectorType}<{Op1BaseType}>* pFld1 = &test._fld1) + fixed ({Op2VectorType}<{Op2BaseType}>* pFld2 = &test._fld2) + { + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(pFld1)), + {LoadIsa}.Load{Op2VectorType}(({Op2BaseType}*)(pFld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2, _fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed ({Op1VectorType}<{Op1BaseType}>* pFld1 = &_fld1) + fixed ({Op2VectorType}<{Op2BaseType}>* pFld2 = &_fld2) + { + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(pFld1)), + {LoadIsa}.Load{Op2VectorType}(({Op2BaseType}*)(pFld2)), + _fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fldImm, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2, test._fldImm); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(&test._fld1)), + {LoadIsa}.Load{Op2VectorType}(({Op2BaseType}*)(&test._fld2)), + test._fldImm + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fldImm, _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, {Op2VectorType}<{Op2BaseType}> op2, {ImmType} imm, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, {ImmType} imm, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, imm, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] left, {Op2BaseType}[] right, {ImmType} imm, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2VectorType}<{Op2BaseType}>, {ImmType}): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" imm: ({imm})"); + 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 080c7b1f5d1fb2..addca4eb30f6fd 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 @@ -7440,6 +7440,230 @@ internal Arm64() { } /// public static Vector128 ReciprocalStep(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + /// + /// uint8x8_t vsli_n_u8(uint8x8_t a, uint8x8_t b, __builtin_constant_p(n)) + /// A32: VSLI.8 Dd, Dm, #n + /// A64: SLI Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogicalAndInsert(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vsli_n_s16(int16x4_t a, int16x4_t b, __builtin_constant_p(n)) + /// A32: VSLI.16 Dd, Dm, #n + /// A64: SLI Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogicalAndInsert(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vsli_n_s32(int32x2_t a, int32x2_t b, __builtin_constant_p(n)) + /// A32: VSLI.32 Dd, Dm, #n + /// A64: SLI Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogicalAndInsert(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vsli_n_s8(int8x8_t a, int8x8_t b, __builtin_constant_p(n)) + /// A32: VSLI.8 Dd, Dm, #n + /// A64: SLI Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogicalAndInsert(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vsli_n_u16(uint16x4_t a, uint16x4_t b, __builtin_constant_p(n)) + /// A32: VSLI.16 Dd, Dm, #n + /// A64: SLI Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogicalAndInsert(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vsli_n_u32(uint32x2_t a, uint32x2_t b, __builtin_constant_p(n)) + /// A32: VSLI.32 Dd, Dm, #n + /// A64: SLI Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogicalAndInsert(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vsliq_n_u8(uint8x16_t a, uint8x16_t b, __builtin_constant_p(n)) + /// A32: VSLI.8 Qd, Qm, #n + /// A64: SLI Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vsliq_n_s16(int16x8_t a, int16x8_t b, __builtin_constant_p(n)) + /// A32: VSLI.16 Qd, Qm, #n + /// A64: SLI Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vsliq_n_s32(int32x4_t a, int32x4_t b, __builtin_constant_p(n)) + /// A32: VSLI.32 Qd, Qm, #n + /// A64: SLI Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vsliq_n_s64(int64x2_t a, int64x2_t b, __builtin_constant_p(n)) + /// A32: VSLI.64 Qd, Qm, #n + /// A64: SLI Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vsliq_n_s8(int8x16_t a, int8x16_t b, __builtin_constant_p(n)) + /// A32: VSLI.8 Qd, Qm, #n + /// A64: SLI Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vsliq_n_u16(uint16x8_t a, uint16x8_t b, __builtin_constant_p(n)) + /// A32: VSLI.16 Qd, Qm, #n + /// A64: SLI Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vsliq_n_u32(uint32x4_t a, uint32x4_t b, __builtin_constant_p(n)) + /// A32: VSLI.32 Qd, Qm, #n + /// A64: SLI Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vsliq_n_u64(uint64x2_t a, uint64x2_t b, __builtin_constant_p(n)) + /// A32: VSLI.64 Qd, Qm, #n + /// A64: SLI Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t vslid_n_s64(int64_t a, int64_t b, __builtin_constant_p(n)) + /// A32: VSLI.64 Dd, Dm, #n + /// A64: SLI Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalAndInsertScalar(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t vslid_n_u64(uint64_t a, uint64_t b, __builtin_constant_p(n)) + /// A32: VSLI.64 Dd, Dm, #n + /// A64: SLI Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalAndInsertScalar(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vsri_n_u8(uint8x8_t a, uint8x8_t b, __builtin_constant_p(n)) + /// A32: VSRI.8 Dd, Dm, #n + /// A64: SRI Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightAndInsert(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vsri_n_s16(int16x4_t a, int16x4_t b, __builtin_constant_p(n)) + /// A32: VSRI.16 Dd, Dm, #n + /// A64: SRI Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightAndInsert(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vsri_n_s32(int32x2_t a, int32x2_t b, __builtin_constant_p(n)) + /// A32: VSRI.32 Dd, Dm, #n + /// A64: SRI Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightAndInsert(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vsri_n_s8(int8x8_t a, int8x8_t b, __builtin_constant_p(n)) + /// A32: VSRI.8 Dd, Dm, #n + /// A64: SRI Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightAndInsert(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vsri_n_u16(uint16x4_t a, uint16x4_t b, __builtin_constant_p(n)) + /// A32: VSRI.16 Dd, Dm, #n + /// A64: SRI Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightAndInsert(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vsri_n_u32(uint32x2_t a, uint32x2_t b, __builtin_constant_p(n)) + /// A32: VSRI.32 Dd, Dm, #n + /// A64: SRI Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightAndInsert(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vsriq_n_u8(uint8x16_t a, uint8x16_t b, __builtin_constant_p(n)) + /// A32: VSRI.8 Qd, Qm, #n + /// A64: SRI Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vsriq_n_s16(int16x8_t a, int16x8_t b, __builtin_constant_p(n)) + /// A32: VSRI.16 Qd, Qm, #n + /// A64: SRI Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vsriq_n_s32(int32x4_t a, int32x4_t b, __builtin_constant_p(n)) + /// A32: VSRI.32 Qd, Qm, #n + /// A64: SRI Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vsriq_n_s64(int64x2_t a, int64x2_t b, __builtin_constant_p(n)) + /// A32: VSRI.64 Qd, Qm, #n + /// A64: SRI Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vsriq_n_s8(int8x16_t a, int8x16_t b, __builtin_constant_p(n)) + /// A32: VSRI.8 Qd, Qm, #n + /// A64: SRI Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vsriq_n_u16(uint16x8_t a, uint16x8_t b, __builtin_constant_p(n)) + /// A32: VSRI.16 Qd, Qm, #n + /// A64: SRI Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vsriq_n_u32(uint32x4_t a, uint32x4_t b, __builtin_constant_p(n)) + /// A32: VSRI.32 Qd, Qm, #n + /// A64: SRI Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vsriq_n_u64(uint64x2_t a, uint64x2_t b, __builtin_constant_p(n)) + /// A32: VSRI.64 Qd, Qm, #n + /// A64: SRI Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t vsrid_n_s64(int64_t a, int64_t b, __builtin_constant_p(n)) + /// A32: VSRI.64 Dd, Dm, #n + /// A64: SRI Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalAndInsertScalar(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t vsrid_n_u64(uint64_t a, uint64_t b, __builtin_constant_p(n)) + /// A32: VSRI.64 Dd, Dm, #n + /// A64: SRI Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalAndInsertScalar(Vector64 left, Vector64 right, byte shift) { throw new PlatformNotSupportedException(); } + /// /// int16x4_t vshl_s16 (int16x4_t a, int16x4_t b) /// A32: VSHL.S16 Dd, Dn, Dm 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 72233956e18299..2b4c26cce5fa12 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 @@ -7442,6 +7442,230 @@ internal Arm64() { } /// public static Vector128 ReciprocalStep(Vector128 left, Vector128 right) => ReciprocalStep(left, right); + /// + /// uint8x8_t vsli_n_u8(uint8x8_t a, uint8x8_t b, __builtin_constant_p(n)) + /// A32: VSLI.8 Dd, Dm, #n + /// A64: SLI Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogicalAndInsert(Vector64 left, Vector64 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// int16x4_t vsli_n_s16(int16x4_t a, int16x4_t b, __builtin_constant_p(n)) + /// A32: VSLI.16 Dd, Dm, #n + /// A64: SLI Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogicalAndInsert(Vector64 left, Vector64 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// int32x2_t vsli_n_s32(int32x2_t a, int32x2_t b, __builtin_constant_p(n)) + /// A32: VSLI.32 Dd, Dm, #n + /// A64: SLI Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogicalAndInsert(Vector64 left, Vector64 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// int8x8_t vsli_n_s8(int8x8_t a, int8x8_t b, __builtin_constant_p(n)) + /// A32: VSLI.8 Dd, Dm, #n + /// A64: SLI Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogicalAndInsert(Vector64 left, Vector64 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// uint16x4_t vsli_n_u16(uint16x4_t a, uint16x4_t b, __builtin_constant_p(n)) + /// A32: VSLI.16 Dd, Dm, #n + /// A64: SLI Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogicalAndInsert(Vector64 left, Vector64 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// uint32x2_t vsli_n_u32(uint32x2_t a, uint32x2_t b, __builtin_constant_p(n)) + /// A32: VSLI.32 Dd, Dm, #n + /// A64: SLI Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogicalAndInsert(Vector64 left, Vector64 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// uint8x16_t vsliq_n_u8(uint8x16_t a, uint8x16_t b, __builtin_constant_p(n)) + /// A32: VSLI.8 Qd, Qm, #n + /// A64: SLI Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// int16x8_t vsliq_n_s16(int16x8_t a, int16x8_t b, __builtin_constant_p(n)) + /// A32: VSLI.16 Qd, Qm, #n + /// A64: SLI Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// int32x4_t vsliq_n_s32(int32x4_t a, int32x4_t b, __builtin_constant_p(n)) + /// A32: VSLI.32 Qd, Qm, #n + /// A64: SLI Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// int64x2_t vsliq_n_s64(int64x2_t a, int64x2_t b, __builtin_constant_p(n)) + /// A32: VSLI.64 Qd, Qm, #n + /// A64: SLI Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// int8x16_t vsliq_n_s8(int8x16_t a, int8x16_t b, __builtin_constant_p(n)) + /// A32: VSLI.8 Qd, Qm, #n + /// A64: SLI Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// uint16x8_t vsliq_n_u16(uint16x8_t a, uint16x8_t b, __builtin_constant_p(n)) + /// A32: VSLI.16 Qd, Qm, #n + /// A64: SLI Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// uint32x4_t vsliq_n_u32(uint32x4_t a, uint32x4_t b, __builtin_constant_p(n)) + /// A32: VSLI.32 Qd, Qm, #n + /// A64: SLI Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// uint64x2_t vsliq_n_u64(uint64x2_t a, uint64x2_t b, __builtin_constant_p(n)) + /// A32: VSLI.64 Qd, Qm, #n + /// A64: SLI Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogicalAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftLeftLogicalAndInsert(left, right, shift); + + /// + /// int64_t vslid_n_s64(int64_t a, int64_t b, __builtin_constant_p(n)) + /// A32: VSLI.64 Dd, Dm, #n + /// A64: SLI Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalAndInsertScalar(Vector64 left, Vector64 right, byte shift) => ShiftLeftLogicalAndInsertScalar(left, right, shift); + + /// + /// uint64_t vslid_n_u64(uint64_t a, uint64_t b, __builtin_constant_p(n)) + /// A32: VSLI.64 Dd, Dm, #n + /// A64: SLI Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalAndInsertScalar(Vector64 left, Vector64 right, byte shift) => ShiftLeftLogicalAndInsertScalar(left, right, shift); + + /// + /// uint8x8_t vsri_n_u8(uint8x8_t a, uint8x8_t b, __builtin_constant_p(n)) + /// A32: VSRI.8 Dd, Dm, #n + /// A64: SRI Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightAndInsert(Vector64 left, Vector64 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// int16x4_t vsri_n_s16(int16x4_t a, int16x4_t b, __builtin_constant_p(n)) + /// A32: VSRI.16 Dd, Dm, #n + /// A64: SRI Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightAndInsert(Vector64 left, Vector64 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// int32x2_t vsri_n_s32(int32x2_t a, int32x2_t b, __builtin_constant_p(n)) + /// A32: VSRI.32 Dd, Dm, #n + /// A64: SRI Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightAndInsert(Vector64 left, Vector64 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// int8x8_t vsri_n_s8(int8x8_t a, int8x8_t b, __builtin_constant_p(n)) + /// A32: VSRI.8 Dd, Dm, #n + /// A64: SRI Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightAndInsert(Vector64 left, Vector64 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// uint16x4_t vsri_n_u16(uint16x4_t a, uint16x4_t b, __builtin_constant_p(n)) + /// A32: VSRI.16 Dd, Dm, #n + /// A64: SRI Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightAndInsert(Vector64 left, Vector64 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// uint32x2_t vsri_n_u32(uint32x2_t a, uint32x2_t b, __builtin_constant_p(n)) + /// A32: VSRI.32 Dd, Dm, #n + /// A64: SRI Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightAndInsert(Vector64 left, Vector64 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// uint8x16_t vsriq_n_u8(uint8x16_t a, uint8x16_t b, __builtin_constant_p(n)) + /// A32: VSRI.8 Qd, Qm, #n + /// A64: SRI Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// int16x8_t vsriq_n_s16(int16x8_t a, int16x8_t b, __builtin_constant_p(n)) + /// A32: VSRI.16 Qd, Qm, #n + /// A64: SRI Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// int32x4_t vsriq_n_s32(int32x4_t a, int32x4_t b, __builtin_constant_p(n)) + /// A32: VSRI.32 Qd, Qm, #n + /// A64: SRI Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// int64x2_t vsriq_n_s64(int64x2_t a, int64x2_t b, __builtin_constant_p(n)) + /// A32: VSRI.64 Qd, Qm, #n + /// A64: SRI Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// int8x16_t vsriq_n_s8(int8x16_t a, int8x16_t b, __builtin_constant_p(n)) + /// A32: VSRI.8 Qd, Qm, #n + /// A64: SRI Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// uint16x8_t vsriq_n_u16(uint16x8_t a, uint16x8_t b, __builtin_constant_p(n)) + /// A32: VSRI.16 Qd, Qm, #n + /// A64: SRI Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// uint32x4_t vsriq_n_u32(uint32x4_t a, uint32x4_t b, __builtin_constant_p(n)) + /// A32: VSRI.32 Qd, Qm, #n + /// A64: SRI Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// uint64x2_t vsriq_n_u64(uint64x2_t a, uint64x2_t b, __builtin_constant_p(n)) + /// A32: VSRI.64 Qd, Qm, #n + /// A64: SRI Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightAndInsert(Vector128 left, Vector128 right, byte shift) => ShiftRightAndInsert(left, right, shift); + + /// + /// int64_t vsrid_n_s64(int64_t a, int64_t b, __builtin_constant_p(n)) + /// A32: VSRI.64 Dd, Dm, #n + /// A64: SRI Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalAndInsertScalar(Vector64 left, Vector64 right, byte shift) => ShiftRightLogicalAndInsertScalar(left, right, shift); + + /// + /// uint64_t vsrid_n_u64(uint64_t a, uint64_t b, __builtin_constant_p(n)) + /// A32: VSRI.64 Dd, Dm, #n + /// A64: SRI Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalAndInsertScalar(Vector64 left, Vector64 right, byte shift) => ShiftRightLogicalAndInsertScalar(left, right, shift); + /// /// int16x4_t vshl_s16 (int16x4_t a, int16x4_t b) /// A32: VSHL.S16 Dd, Dn, Dm diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index fdcb8c1aa1f233..ab47d9f0e44f6f 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -1057,6 +1057,38 @@ internal AdvSimd() { } public static System.Runtime.Intrinsics.Vector64 ReciprocalSquareRootStep(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 ReciprocalStep(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 ReciprocalStep(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalAndInsertScalar(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalAndInsertScalar(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightAndInsert(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalAndInsertScalar(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalAndInsertScalar(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, byte shift) { throw null; } public static System.Runtime.Intrinsics.Vector128 ShiftArithmetic(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } public static System.Runtime.Intrinsics.Vector128 ShiftArithmetic(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } public static System.Runtime.Intrinsics.Vector128 ShiftArithmetic(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; }