From 4cdeba726f443bdc8972b084d0ca874bb8373d42 Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Thu, 7 Nov 2019 11:28:57 -0800 Subject: [PATCH 1/9] Add Crc32 instructions in jit/emitarm64.cpp jit/instrsarm64.h --- src/coreclr/src/jit/emitarm64.cpp | 8 ++++++++ src/coreclr/src/jit/instrsarm64.h | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/coreclr/src/jit/emitarm64.cpp b/src/coreclr/src/jit/emitarm64.cpp index de881696f396ad..ef3a73ac05196d 100644 --- a/src/coreclr/src/jit/emitarm64.cpp +++ b/src/coreclr/src/jit/emitarm64.cpp @@ -5161,6 +5161,14 @@ void emitter::emitIns_R_R_R( case INS_lsrv: case INS_asrv: case INS_rorv: + case INS_crc32b: + case INS_crc32h: + case INS_crc32w: + case INS_crc32x: + case INS_crc32cb: + case INS_crc32ch: + case INS_crc32cw: + case INS_crc32cx: assert(insOptsNone(opt)); assert(isValidGeneralDatasize(size)); assert(isGeneralRegister(reg1)); diff --git a/src/coreclr/src/jit/instrsarm64.h b/src/coreclr/src/jit/instrsarm64.h index ba33abad71860b..d7a3837e74ac85 100644 --- a/src/coreclr/src/jit/instrsarm64.h +++ b/src/coreclr/src/jit/instrsarm64.h @@ -1051,6 +1051,30 @@ INST1(asrv, "asrv", 0, 0, IF_DR_3A, 0x1AC02800) INST1(rorv, "rorv", 0, 0, IF_DR_3A, 0x1AC02C00) // rorv Rd,Rn,Rm DR_3A X0011010110mmmmm 001011nnnnnddddd 1AC0 2C00 +INST1(crc32b, "crc32b", 0, 0, IF_DR_3A, 0x1AC04000) + // crc32b Rd,Rn,Rm DR_3A 00011010110mmmmm 010000nnnnnddddd 1AC0 4000 + +INST1(crc32h, "crc32h", 0, 0, IF_DR_3A, 0x1AC04400) + // crc32h Rd,Rn,Rm DR_3A 00011010110mmmmm 010001nnnnnddddd 1AC0 4400 + +INST1(crc32w, "crc32w", 0, 0, IF_DR_3A, 0x1AC04800) + // crc32w Rd,Rn,Rm DR_3A 00011010110mmmmm 010010nnnnnddddd 1AC0 4800 + +INST1(crc32x, "crc32x", 0, 0, IF_DR_3A, 0x9AC04C00) + // crc32x Rd,Rn,Xm DR_3A 10011010110mmmmm 010011nnnnnddddd 9AC0 4C00 + +INST1(crc32cb, "crc32cb",0, 0, IF_DR_3A, 0x1AC05000) + // crc32cb Rd,Rn,Rm DR_3A 00011010110mmmmm 010100nnnnnddddd 1AC0 5000 + +INST1(crc32ch, "crc32ch",0, 0, IF_DR_3A, 0x1AC05400) + // crc32ch Rd,Rn,Rm DR_3A 00011010110mmmmm 010101nnnnnddddd 1AC0 5400 + +INST1(crc32cw, "crc32cw",0, 0, IF_DR_3A, 0x1AC05800) + // crc32cw Rd,Rn,Rm DR_3A 00011010110mmmmm 010110nnnnnddddd 1AC0 5800 + +INST1(crc32cx, "crc32cx",0, 0, IF_DR_3A, 0x9AC05C00) + // crc32cx Rd,Rn,Xm DR_3A 10011010110mmmmm 010111nnnnnddddd 9AC0 5C00 + INST1(sha1c, "sha1c", 0, 0, IF_DV_3F, 0x5E000000) // sha1c Qd, Sn Vm.4S DV_3F 01011110000mmmmm 000000nnnnnddddd 5E00 0000 Qd Sn Vm.4S (vector) From 9e7f36f8f6ba4bdbc7a60d4f350ff8151d520610 Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Thu, 7 Nov 2019 12:58:42 -0800 Subject: [PATCH 2/9] Add entry to InstructionSet enum corresponding to Crc32 64-bit Isa in jit/instr.h --- src/coreclr/src/jit/instr.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/src/jit/instr.h b/src/coreclr/src/jit/instr.h index 44a908a8516181..fdde64838672b0 100644 --- a/src/coreclr/src/jit/instr.h +++ b/src/coreclr/src/jit/instr.h @@ -336,6 +336,7 @@ enum InstructionSet InstructionSet_ArmBase_Arm64, InstructionSet_Atomics, // ID_AA64ISAR0_EL1.Atomic is 2 or better InstructionSet_Crc32, // ID_AA64ISAR0_EL1.CRC32 is 1 or better + InstructionSet_Crc32_Arm64, InstructionSet_Dcpop, // ID_AA64ISAR1_EL1.DPB is 1 or better InstructionSet_Dp, // ID_AA64ISAR0_EL1.DP is 1 or better InstructionSet_Fcma, // ID_AA64ISAR1_EL1.FCMA is 1 or better From 02e8f3fd979ca5a34aada7a337bcfe402e72710e Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Thu, 7 Nov 2019 10:29:42 -0800 Subject: [PATCH 3/9] Define Crc32 intrinsics in jit/hwintrinsiclistarm64.h --- src/coreclr/src/jit/hwintrinsiclistarm64.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/coreclr/src/jit/hwintrinsiclistarm64.h b/src/coreclr/src/jit/hwintrinsiclistarm64.h index bf8e019c9747f0..1f568e9fb3f60a 100644 --- a/src/coreclr/src/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/src/jit/hwintrinsiclistarm64.h @@ -92,6 +92,22 @@ HARDWARE_INTRINSIC(ArmBase, LeadingZeroCount, - HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingSignCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment) HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingZeroCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment) +// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +// ISA Function name ival SIMD size NumArg instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +// CRC32 Intrinsics +HARDWARE_INTRINSIC(Crc32, ComputeCrc32, -1, 0, 2, {INS_invalid, INS_crc32b, INS_invalid, INS_crc32h, INS_invalid, INS_crc32w, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(Crc32, ComputeCrc32C, -1, 0, 2, {INS_invalid, INS_crc32cb, INS_invalid, INS_crc32ch, INS_invalid, INS_crc32cw, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) + +// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +// ISA Function name ival SIMD size NumArg instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +// CRC32 64-bit only Intrinsics +HARDWARE_INTRINSIC(Crc32_Arm64, ComputeCrc32, -1, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32x, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(Crc32_Arm64, ComputeCrc32C, -1, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32cx, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) + // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name ival SIMD size NumArg instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} From 48343f6a54e72df19b86aafb04a6d2a5e74cebad Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Thu, 7 Nov 2019 12:59:53 -0800 Subject: [PATCH 4/9] Implement Crc32 and Crc32_Arm64 instruction sets in jit/hwintrinsicarm64.cpp --- src/coreclr/src/jit/hwintrinsicarm64.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/coreclr/src/jit/hwintrinsicarm64.cpp b/src/coreclr/src/jit/hwintrinsicarm64.cpp index c52e35468b95c3..2db01d6c20b8e8 100644 --- a/src/coreclr/src/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/src/jit/hwintrinsicarm64.cpp @@ -23,6 +23,8 @@ static InstructionSet Arm64VersionOfIsa(InstructionSet isa) return InstructionSet_AdvSimd_Arm64; case InstructionSet_ArmBase: return InstructionSet_ArmBase_Arm64; + case InstructionSet_Crc32: + return InstructionSet_Crc32_Arm64; default: unreached(); } @@ -55,6 +57,13 @@ static InstructionSet lookupInstructionSet(const char* className) return InstructionSet_ArmBase; } } + else if (className[0] == 'C') + { + if (strcmp(className, "Crc32") == 0) + { + return InstructionSet_Crc32; + } + } else if (className[0] == 'S') { if (strcmp(className, "Sha1") == 0) @@ -154,6 +163,8 @@ bool HWIntrinsicInfo::isFullyImplementedIsa(InstructionSet isa) case InstructionSet_Aes: case InstructionSet_ArmBase: case InstructionSet_ArmBase_Arm64: + case InstructionSet_Crc32: + case InstructionSet_Crc32_Arm64: case InstructionSet_Sha1: case InstructionSet_Sha256: case InstructionSet_Vector64: @@ -183,6 +194,8 @@ bool HWIntrinsicInfo::isScalarIsa(InstructionSet isa) { case InstructionSet_ArmBase: case InstructionSet_ArmBase_Arm64: + case InstructionSet_Crc32: + case InstructionSet_Crc32_Arm64: { return true; } From bac6754c975b2e96649b7315e8f9d0a876c85485 Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Mon, 11 Nov 2019 18:33:19 -0800 Subject: [PATCH 5/9] Port ScalarBinOpTest.template to Arm in src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/ScalarBinOpTest.template --- .../Arm/Shared/ScalarBinOpTest.template | 242 ++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/ScalarBinOpTest.template diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/ScalarBinOpTest.template b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/ScalarBinOpTest.template new file mode 100644 index 00000000000000..5a80db1648e53d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/ScalarBinOpTest.template @@ -0,0 +1,242 @@ +// 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 ScalarBinaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ScalarBinaryOpTest__{TestName} + { + private struct TestStruct + { + public {Op1BaseType} _fld1; + public {Op2BaseType} _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + testStruct._fld1 = {NextValueOp1}; + testStruct._fld2 = {NextValueOp2}; + + return testStruct; + } + + public void RunStructFldScenario(ScalarBinaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2); + testClass.ValidateResult(_fld1, _fld2, result); + } + } + + private static {Op1BaseType} _data1; + private static {Op2BaseType} _data2; + + private static {Op1BaseType} _clsVar1; + private static {Op2BaseType} _clsVar2; + + private {Op1BaseType} _fld1; + private {Op2BaseType} _fld2; + + static ScalarBinaryOpTest__{TestName}() + { + _clsVar1 = {NextValueOp1}; + _clsVar2 = {NextValueOp2}; + } + + public ScalarBinaryOpTest__{TestName}() + { + Succeeded = true; + + _fld1 = {NextValueOp1}; + _fld2 = {NextValueOp2}; + + _data1 = {NextValueOp1}; + _data2 = {NextValueOp2}; + } + + 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.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1)), + Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2)) + ); + + ValidateResult(_data1, _data2, result); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1BaseType}), typeof({Op2BaseType}) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1)), + Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2)) + }); + + ValidateResult(_data1, _data2, ({RetBaseType})result); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = {Isa}.{Method}( + _clsVar1, + _clsVar2 + ); + + ValidateResult(_clsVar1, _clsVar2, result); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data1 = Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1)); + var data2 = Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2)); + var result = {Isa}.{Method}(data1, data2); + + ValidateResult(data1, data2, result); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ScalarBinaryOpTest__{TestName}(); + var result = {Isa}.{Method}(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2); + ValidateResult(_fld1, _fld2, result); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1BaseType} left, {Op2BaseType} right, {RetBaseType} result, [CallerMemberName] string method = "") + { + var isUnexpectedResult = false; + + {ValidateResult} + + if (isUnexpectedResult) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1BaseType}, {Op2BaseType}): {Method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: {left}"); + TestLibrary.TestFramework.LogInformation($" right: {right}"); + TestLibrary.TestFramework.LogInformation($" result: {result}"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} From 41d46d966fc81bd881a28ffd960eb94f6d721cdf Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Tue, 12 Nov 2019 16:36:59 -0800 Subject: [PATCH 6/9] Implement ComputeCrc32 in CodeGen::genSpecialIntrinsic in jit/hwintrinsiccodegenarm64.cpp --- .../src/jit/hwintrinsiccodegenarm64.cpp | 60 ++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp index 191ffcba9067ce..3dbd4ea6e8c9b1 100644 --- a/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp @@ -162,7 +162,51 @@ void CodeGen::genSpecialIntrinsic(GenTreeHWIntrinsic* node) GenTree* op2 = node->gtGetOp2(); regNumber targetReg = node->GetRegNum(); var_types targetType = node->TypeGet(); - var_types baseType = (category == HW_Category_Scalar) ? op1->TypeGet() : node->gtSIMDBaseType; + var_types baseType = node->gtSIMDBaseType; + + if (baseType == TYP_UNKNOWN) + { + assert(category == HW_Category_Scalar); + + if (HWIntrinsicInfo::BaseTypeFromFirstArg(intrinsicId)) + { + assert(op1 != nullptr); + baseType = op1->TypeGet(); + } + else if (HWIntrinsicInfo::BaseTypeFromSecondArg(intrinsicId)) + { + assert(op2 != nullptr); + baseType = op2->TypeGet(); + } + else + { + baseType = targetType; + } + } + + switch (intrinsicId) + { + case NI_Crc32_ComputeCrc32: + case NI_Crc32_ComputeCrc32C: + { + if (baseType == TYP_INT) + { + baseType = TYP_UINT; + } + break; + } + + case NI_Crc32_Arm64_ComputeCrc32: + case NI_Crc32_Arm64_ComputeCrc32C: + { + assert(baseType == TYP_LONG); + baseType = TYP_ULONG; + break; + } + + default: + break; + } instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType); assert(ins != INS_invalid); @@ -215,6 +259,20 @@ void CodeGen::genSpecialIntrinsic(GenTreeHWIntrinsic* node) break; } + case NI_Crc32_ComputeCrc32: + case NI_Crc32_ComputeCrc32C: + case NI_Crc32_Arm64_ComputeCrc32: + case NI_Crc32_Arm64_ComputeCrc32C: + { + assert(op1 != nullptr); + assert(op2 != nullptr); + + op1Reg = op1->GetRegNum(); + op2Reg = op2->GetRegNum(); + emit->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg); + break; + } + default: { unreached(); From 82924d3828f5e3cb0e583d44e658a40c12f38027 Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Tue, 12 Nov 2019 16:47:07 -0800 Subject: [PATCH 7/9] Implement ComputeCrc32 in Compiler::impSpecialIntrinsic in jit/hwintrinsicarm64.cpp --- src/coreclr/src/jit/hwintrinsicarm64.cpp | 26 +++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/coreclr/src/jit/hwintrinsicarm64.cpp b/src/coreclr/src/jit/hwintrinsicarm64.cpp index 2db01d6c20b8e8..24364f2fb698e0 100644 --- a/src/coreclr/src/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/src/jit/hwintrinsicarm64.cpp @@ -260,10 +260,15 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, } } - if (HWIntrinsicInfo::BaseTypeFromFirstArg(intrinsic)) + if (HWIntrinsicInfo::BaseTypeFromFirstArg(intrinsic) || HWIntrinsicInfo::BaseTypeFromSecondArg(intrinsic)) { CORINFO_ARG_LIST_HANDLE arg = sig->args; + if (HWIntrinsicInfo::BaseTypeFromSecondArg(intrinsic)) + { + arg = info.compCompHnd->getArgNext(arg); + } + CORINFO_CLASS_HANDLE argClass = info.compCompHnd->getArgClass(sig, arg); baseType = getBaseTypeAndSizeOfSIMDType(argClass); @@ -372,6 +377,25 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, return gtNewScalarHWIntrinsicNode(baseType, op1, intrinsic); } + case NI_Crc32_ComputeCrc32: + case NI_Crc32_ComputeCrc32C: + case NI_Crc32_Arm64_ComputeCrc32: + case NI_Crc32_Arm64_ComputeCrc32C: + { + assert(numArgs == 2); + + argType = JITtype2varType( + strip(info.compCompHnd->getArgType(sig, info.compCompHnd->getArgNext(argList), &argClass))); + op2 = getArgForHWIntrinsic(argType, argClass); + + argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); + op1 = getArgForHWIntrinsic(argType, argClass); + + retNode = gtNewScalarHWIntrinsicNode(retType, op1, op2, intrinsic); + retNode->AsHWIntrinsic()->gtSIMDBaseType = baseType; + break; + } + default: { unreached(); From 982006b79cbe77f8757f8abc52ec17c220ffe203 Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Mon, 11 Nov 2019 18:46:41 -0800 Subject: [PATCH 8/9] Add Crc32 ComputeCrc32 tests in tests\src\JIT\HardwareIntrinsics\Arm --- .../Arm/Crc32.Arm64/ComputeCrc32.UInt64.cs | 242 ++++++++++++++++++ .../Arm/Crc32.Arm64/ComputeCrc32C.UInt64.cs | 242 ++++++++++++++++++ .../Arm/Crc32.Arm64/Crc32.Arm64_r.csproj | 17 ++ .../Arm/Crc32.Arm64/Crc32.Arm64_ro.csproj | 17 ++ .../Arm/Crc32.Arm64/Program.Crc32.Arm64.cs | 20 ++ .../Arm/Crc32/ComputeCrc32.Byte.cs | 242 ++++++++++++++++++ .../Arm/Crc32/ComputeCrc32.UInt16.cs | 242 ++++++++++++++++++ .../Arm/Crc32/ComputeCrc32.UInt32.cs | 242 ++++++++++++++++++ .../Arm/Crc32/ComputeCrc32C.Byte.cs | 242 ++++++++++++++++++ .../Arm/Crc32/ComputeCrc32C.UInt16.cs | 242 ++++++++++++++++++ .../Arm/Crc32/ComputeCrc32C.UInt32.cs | 242 ++++++++++++++++++ .../Arm/Crc32/Crc32_r.csproj | 21 ++ .../Arm/Crc32/Crc32_ro.csproj | 21 ++ .../Arm/Crc32/Program.Crc32.cs | 24 ++ .../Arm/Shared/GenerateTests.csx | 18 ++ .../HardwareIntrinsics/Arm/Shared/Program.cs | 1 + 16 files changed, 2075 insertions(+) create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/ComputeCrc32.UInt64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/ComputeCrc32C.UInt64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/Crc32.Arm64_r.csproj create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/Crc32.Arm64_ro.csproj create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/Program.Crc32.Arm64.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32.Byte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32.UInt16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32.UInt32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32C.Byte.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32C.UInt16.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32C.UInt32.cs create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/Crc32_r.csproj create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/Crc32_ro.csproj create mode 100644 src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/Program.Crc32.cs diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/ComputeCrc32.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/ComputeCrc32.UInt64.cs new file mode 100644 index 00000000000000..5650ef6f74f4e5 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/ComputeCrc32.UInt64.cs @@ -0,0 +1,242 @@ +// 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 ComputeCrc32_UInt64() + { + var test = new ScalarBinaryOpTest__ComputeCrc32_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ScalarBinaryOpTest__ComputeCrc32_UInt64 + { + private struct TestStruct + { + public UInt32 _fld1; + public UInt64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + testStruct._fld1 = 0xFFFFFFFF; + testStruct._fld2 = 0x20191113110219UL; + + return testStruct; + } + + public void RunStructFldScenario(ScalarBinaryOpTest__ComputeCrc32_UInt64 testClass) + { + var result = Crc32.Arm64.ComputeCrc32(_fld1, _fld2); + testClass.ValidateResult(_fld1, _fld2, result); + } + } + + private static UInt32 _data1; + private static UInt64 _data2; + + private static UInt32 _clsVar1; + private static UInt64 _clsVar2; + + private UInt32 _fld1; + private UInt64 _fld2; + + static ScalarBinaryOpTest__ComputeCrc32_UInt64() + { + _clsVar1 = 0xFFFFFFFF; + _clsVar2 = 0x20191113110219UL; + } + + public ScalarBinaryOpTest__ComputeCrc32_UInt64() + { + Succeeded = true; + + _fld1 = 0xFFFFFFFF; + _fld2 = 0x20191113110219UL; + + _data1 = 0xFFFFFFFF; + _data2 = 0x20191113110219UL; + } + + public bool IsSupported => Crc32.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Crc32.Arm64.ComputeCrc32( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + ); + + ValidateResult(_data1, _data2, result); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Crc32.Arm64).GetMethod(nameof(Crc32.Arm64.ComputeCrc32), new Type[] { typeof(UInt32), typeof(UInt64) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + }); + + ValidateResult(_data1, _data2, (UInt32)result); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Crc32.Arm64.ComputeCrc32( + _clsVar1, + _clsVar2 + ); + + ValidateResult(_clsVar1, _clsVar2, result); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data1 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)); + var data2 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)); + var result = Crc32.Arm64.ComputeCrc32(data1, data2); + + ValidateResult(data1, data2, result); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ScalarBinaryOpTest__ComputeCrc32_UInt64(); + var result = Crc32.Arm64.ComputeCrc32(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Crc32.Arm64.ComputeCrc32(_fld1, _fld2); + ValidateResult(_fld1, _fld2, result); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Crc32.Arm64.ComputeCrc32(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(UInt32 left, UInt64 right, UInt32 result, [CallerMemberName] string method = "") + { + var isUnexpectedResult = false; + + uint expectedResult = 0xEFAAAB74; isUnexpectedResult = (expectedResult != result); + + if (isUnexpectedResult) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Crc32.Arm64)}.{nameof(Crc32.Arm64.ComputeCrc32)}(UInt32, UInt64): ComputeCrc32 failed:"); + TestLibrary.TestFramework.LogInformation($" left: {left}"); + TestLibrary.TestFramework.LogInformation($" right: {right}"); + TestLibrary.TestFramework.LogInformation($" result: {result}"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/ComputeCrc32C.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/ComputeCrc32C.UInt64.cs new file mode 100644 index 00000000000000..a62e34b00e355a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/ComputeCrc32C.UInt64.cs @@ -0,0 +1,242 @@ +// 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 ComputeCrc32C_UInt64() + { + var test = new ScalarBinaryOpTest__ComputeCrc32C_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ScalarBinaryOpTest__ComputeCrc32C_UInt64 + { + private struct TestStruct + { + public UInt32 _fld1; + public UInt64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + testStruct._fld1 = 0xFFFFFFFF; + testStruct._fld2 = 0x20191113110219UL; + + return testStruct; + } + + public void RunStructFldScenario(ScalarBinaryOpTest__ComputeCrc32C_UInt64 testClass) + { + var result = Crc32.Arm64.ComputeCrc32C(_fld1, _fld2); + testClass.ValidateResult(_fld1, _fld2, result); + } + } + + private static UInt32 _data1; + private static UInt64 _data2; + + private static UInt32 _clsVar1; + private static UInt64 _clsVar2; + + private UInt32 _fld1; + private UInt64 _fld2; + + static ScalarBinaryOpTest__ComputeCrc32C_UInt64() + { + _clsVar1 = 0xFFFFFFFF; + _clsVar2 = 0x20191113110219UL; + } + + public ScalarBinaryOpTest__ComputeCrc32C_UInt64() + { + Succeeded = true; + + _fld1 = 0xFFFFFFFF; + _fld2 = 0x20191113110219UL; + + _data1 = 0xFFFFFFFF; + _data2 = 0x20191113110219UL; + } + + public bool IsSupported => Crc32.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Crc32.Arm64.ComputeCrc32C( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + ); + + ValidateResult(_data1, _data2, result); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Crc32.Arm64).GetMethod(nameof(Crc32.Arm64.ComputeCrc32C), new Type[] { typeof(UInt32), typeof(UInt64) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + }); + + ValidateResult(_data1, _data2, (UInt32)result); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Crc32.Arm64.ComputeCrc32C( + _clsVar1, + _clsVar2 + ); + + ValidateResult(_clsVar1, _clsVar2, result); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data1 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)); + var data2 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)); + var result = Crc32.Arm64.ComputeCrc32C(data1, data2); + + ValidateResult(data1, data2, result); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ScalarBinaryOpTest__ComputeCrc32C_UInt64(); + var result = Crc32.Arm64.ComputeCrc32C(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Crc32.Arm64.ComputeCrc32C(_fld1, _fld2); + ValidateResult(_fld1, _fld2, result); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Crc32.Arm64.ComputeCrc32C(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(UInt32 left, UInt64 right, UInt32 result, [CallerMemberName] string method = "") + { + var isUnexpectedResult = false; + + uint expectedResult = 0x6295C71A; isUnexpectedResult = (expectedResult != result); + + if (isUnexpectedResult) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Crc32.Arm64)}.{nameof(Crc32.Arm64.ComputeCrc32C)}(UInt32, UInt64): ComputeCrc32C failed:"); + TestLibrary.TestFramework.LogInformation($" left: {left}"); + TestLibrary.TestFramework.LogInformation($" right: {right}"); + TestLibrary.TestFramework.LogInformation($" result: {result}"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/Crc32.Arm64_r.csproj b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/Crc32.Arm64_r.csproj new file mode 100644 index 00000000000000..552bd67191f55f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/Crc32.Arm64_r.csproj @@ -0,0 +1,17 @@ + + + Exe + true + + + Embedded + + + + + + + + + + diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/Crc32.Arm64_ro.csproj b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/Crc32.Arm64_ro.csproj new file mode 100644 index 00000000000000..20d702e41055c9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/Crc32.Arm64_ro.csproj @@ -0,0 +1,17 @@ + + + Exe + true + + + Embedded + True + + + + + + + + + diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/Program.Crc32.Arm64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/Program.Crc32.Arm64.cs new file mode 100644 index 00000000000000..8e078039264309 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32.Arm64/Program.Crc32.Arm64.cs @@ -0,0 +1,20 @@ +// 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. + +using System; +using System.Collections.Generic; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + static Program() + { + TestList = new Dictionary() { + ["ComputeCrc32.UInt64"] = ComputeCrc32_UInt64, + ["ComputeCrc32C.UInt64"] = ComputeCrc32C_UInt64, + }; + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32.Byte.cs new file mode 100644 index 00000000000000..033c9c22af20bd --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32.Byte.cs @@ -0,0 +1,242 @@ +// 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 ComputeCrc32_Byte() + { + var test = new ScalarBinaryOpTest__ComputeCrc32_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ScalarBinaryOpTest__ComputeCrc32_Byte + { + private struct TestStruct + { + public UInt32 _fld1; + public Byte _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + testStruct._fld1 = 0xFFFFFFFF; + testStruct._fld2 = 0x20; + + return testStruct; + } + + public void RunStructFldScenario(ScalarBinaryOpTest__ComputeCrc32_Byte testClass) + { + var result = Crc32.ComputeCrc32(_fld1, _fld2); + testClass.ValidateResult(_fld1, _fld2, result); + } + } + + private static UInt32 _data1; + private static Byte _data2; + + private static UInt32 _clsVar1; + private static Byte _clsVar2; + + private UInt32 _fld1; + private Byte _fld2; + + static ScalarBinaryOpTest__ComputeCrc32_Byte() + { + _clsVar1 = 0xFFFFFFFF; + _clsVar2 = 0x20; + } + + public ScalarBinaryOpTest__ComputeCrc32_Byte() + { + Succeeded = true; + + _fld1 = 0xFFFFFFFF; + _fld2 = 0x20; + + _data1 = 0xFFFFFFFF; + _data2 = 0x20; + } + + public bool IsSupported => Crc32.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Crc32.ComputeCrc32( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + ); + + ValidateResult(_data1, _data2, result); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Crc32).GetMethod(nameof(Crc32.ComputeCrc32), new Type[] { typeof(UInt32), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + }); + + ValidateResult(_data1, _data2, (UInt32)result); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Crc32.ComputeCrc32( + _clsVar1, + _clsVar2 + ); + + ValidateResult(_clsVar1, _clsVar2, result); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data1 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)); + var data2 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)); + var result = Crc32.ComputeCrc32(data1, data2); + + ValidateResult(data1, data2, result); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ScalarBinaryOpTest__ComputeCrc32_Byte(); + var result = Crc32.ComputeCrc32(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Crc32.ComputeCrc32(_fld1, _fld2); + ValidateResult(_fld1, _fld2, result); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Crc32.ComputeCrc32(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(UInt32 left, Byte right, UInt32 result, [CallerMemberName] string method = "") + { + var isUnexpectedResult = false; + + uint expectedResult = 0x169330BA; isUnexpectedResult = (expectedResult != result); + + if (isUnexpectedResult) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Crc32)}.{nameof(Crc32.ComputeCrc32)}(UInt32, Byte): ComputeCrc32 failed:"); + TestLibrary.TestFramework.LogInformation($" left: {left}"); + TestLibrary.TestFramework.LogInformation($" right: {right}"); + TestLibrary.TestFramework.LogInformation($" result: {result}"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32.UInt16.cs new file mode 100644 index 00000000000000..1b74d34a565abe --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32.UInt16.cs @@ -0,0 +1,242 @@ +// 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 ComputeCrc32_UInt16() + { + var test = new ScalarBinaryOpTest__ComputeCrc32_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ScalarBinaryOpTest__ComputeCrc32_UInt16 + { + private struct TestStruct + { + public UInt32 _fld1; + public UInt16 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + testStruct._fld1 = 0xFFFFFFFF; + testStruct._fld2 = 0x2019; + + return testStruct; + } + + public void RunStructFldScenario(ScalarBinaryOpTest__ComputeCrc32_UInt16 testClass) + { + var result = Crc32.ComputeCrc32(_fld1, _fld2); + testClass.ValidateResult(_fld1, _fld2, result); + } + } + + private static UInt32 _data1; + private static UInt16 _data2; + + private static UInt32 _clsVar1; + private static UInt16 _clsVar2; + + private UInt32 _fld1; + private UInt16 _fld2; + + static ScalarBinaryOpTest__ComputeCrc32_UInt16() + { + _clsVar1 = 0xFFFFFFFF; + _clsVar2 = 0x2019; + } + + public ScalarBinaryOpTest__ComputeCrc32_UInt16() + { + Succeeded = true; + + _fld1 = 0xFFFFFFFF; + _fld2 = 0x2019; + + _data1 = 0xFFFFFFFF; + _data2 = 0x2019; + } + + public bool IsSupported => Crc32.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Crc32.ComputeCrc32( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + ); + + ValidateResult(_data1, _data2, result); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Crc32).GetMethod(nameof(Crc32.ComputeCrc32), new Type[] { typeof(UInt32), typeof(UInt16) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + }); + + ValidateResult(_data1, _data2, (UInt32)result); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Crc32.ComputeCrc32( + _clsVar1, + _clsVar2 + ); + + ValidateResult(_clsVar1, _clsVar2, result); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data1 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)); + var data2 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)); + var result = Crc32.ComputeCrc32(data1, data2); + + ValidateResult(data1, data2, result); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ScalarBinaryOpTest__ComputeCrc32_UInt16(); + var result = Crc32.ComputeCrc32(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Crc32.ComputeCrc32(_fld1, _fld2); + ValidateResult(_fld1, _fld2, result); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Crc32.ComputeCrc32(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(UInt32 left, UInt16 right, UInt32 result, [CallerMemberName] string method = "") + { + var isUnexpectedResult = false; + + uint expectedResult = 0x1E4864D0; isUnexpectedResult = (expectedResult != result); + + if (isUnexpectedResult) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Crc32)}.{nameof(Crc32.ComputeCrc32)}(UInt32, UInt16): ComputeCrc32 failed:"); + TestLibrary.TestFramework.LogInformation($" left: {left}"); + TestLibrary.TestFramework.LogInformation($" right: {right}"); + TestLibrary.TestFramework.LogInformation($" result: {result}"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32.UInt32.cs new file mode 100644 index 00000000000000..69dad8ae26f6c2 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32.UInt32.cs @@ -0,0 +1,242 @@ +// 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 ComputeCrc32_UInt32() + { + var test = new ScalarBinaryOpTest__ComputeCrc32_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ScalarBinaryOpTest__ComputeCrc32_UInt32 + { + private struct TestStruct + { + public UInt32 _fld1; + public UInt32 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + testStruct._fld1 = 0xFFFFFFFF; + testStruct._fld2 = 0x20191113; + + return testStruct; + } + + public void RunStructFldScenario(ScalarBinaryOpTest__ComputeCrc32_UInt32 testClass) + { + var result = Crc32.ComputeCrc32(_fld1, _fld2); + testClass.ValidateResult(_fld1, _fld2, result); + } + } + + private static UInt32 _data1; + private static UInt32 _data2; + + private static UInt32 _clsVar1; + private static UInt32 _clsVar2; + + private UInt32 _fld1; + private UInt32 _fld2; + + static ScalarBinaryOpTest__ComputeCrc32_UInt32() + { + _clsVar1 = 0xFFFFFFFF; + _clsVar2 = 0x20191113; + } + + public ScalarBinaryOpTest__ComputeCrc32_UInt32() + { + Succeeded = true; + + _fld1 = 0xFFFFFFFF; + _fld2 = 0x20191113; + + _data1 = 0xFFFFFFFF; + _data2 = 0x20191113; + } + + public bool IsSupported => Crc32.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Crc32.ComputeCrc32( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + ); + + ValidateResult(_data1, _data2, result); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Crc32).GetMethod(nameof(Crc32.ComputeCrc32), new Type[] { typeof(UInt32), typeof(UInt32) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + }); + + ValidateResult(_data1, _data2, (UInt32)result); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Crc32.ComputeCrc32( + _clsVar1, + _clsVar2 + ); + + ValidateResult(_clsVar1, _clsVar2, result); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data1 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)); + var data2 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)); + var result = Crc32.ComputeCrc32(data1, data2); + + ValidateResult(data1, data2, result); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ScalarBinaryOpTest__ComputeCrc32_UInt32(); + var result = Crc32.ComputeCrc32(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Crc32.ComputeCrc32(_fld1, _fld2); + ValidateResult(_fld1, _fld2, result); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Crc32.ComputeCrc32(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(UInt32 left, UInt32 right, UInt32 result, [CallerMemberName] string method = "") + { + var isUnexpectedResult = false; + + uint expectedResult = 0x219D9805; isUnexpectedResult = (expectedResult != result); + + if (isUnexpectedResult) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Crc32)}.{nameof(Crc32.ComputeCrc32)}(UInt32, UInt32): ComputeCrc32 failed:"); + TestLibrary.TestFramework.LogInformation($" left: {left}"); + TestLibrary.TestFramework.LogInformation($" right: {right}"); + TestLibrary.TestFramework.LogInformation($" result: {result}"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32C.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32C.Byte.cs new file mode 100644 index 00000000000000..aa557dfa3f5294 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32C.Byte.cs @@ -0,0 +1,242 @@ +// 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 ComputeCrc32C_Byte() + { + var test = new ScalarBinaryOpTest__ComputeCrc32C_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ScalarBinaryOpTest__ComputeCrc32C_Byte + { + private struct TestStruct + { + public UInt32 _fld1; + public Byte _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + testStruct._fld1 = 0xFFFFFFFF; + testStruct._fld2 = 0x20; + + return testStruct; + } + + public void RunStructFldScenario(ScalarBinaryOpTest__ComputeCrc32C_Byte testClass) + { + var result = Crc32.ComputeCrc32C(_fld1, _fld2); + testClass.ValidateResult(_fld1, _fld2, result); + } + } + + private static UInt32 _data1; + private static Byte _data2; + + private static UInt32 _clsVar1; + private static Byte _clsVar2; + + private UInt32 _fld1; + private Byte _fld2; + + static ScalarBinaryOpTest__ComputeCrc32C_Byte() + { + _clsVar1 = 0xFFFFFFFF; + _clsVar2 = 0x20; + } + + public ScalarBinaryOpTest__ComputeCrc32C_Byte() + { + Succeeded = true; + + _fld1 = 0xFFFFFFFF; + _fld2 = 0x20; + + _data1 = 0xFFFFFFFF; + _data2 = 0x20; + } + + public bool IsSupported => Crc32.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Crc32.ComputeCrc32C( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + ); + + ValidateResult(_data1, _data2, result); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Crc32).GetMethod(nameof(Crc32.ComputeCrc32C), new Type[] { typeof(UInt32), typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + }); + + ValidateResult(_data1, _data2, (UInt32)result); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Crc32.ComputeCrc32C( + _clsVar1, + _clsVar2 + ); + + ValidateResult(_clsVar1, _clsVar2, result); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data1 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)); + var data2 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)); + var result = Crc32.ComputeCrc32C(data1, data2); + + ValidateResult(data1, data2, result); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ScalarBinaryOpTest__ComputeCrc32C_Byte(); + var result = Crc32.ComputeCrc32C(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Crc32.ComputeCrc32C(_fld1, _fld2); + ValidateResult(_fld1, _fld2, result); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Crc32.ComputeCrc32C(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(UInt32 left, Byte right, UInt32 result, [CallerMemberName] string method = "") + { + var isUnexpectedResult = false; + + uint expectedResult = 0x8D3F2270; isUnexpectedResult = (expectedResult != result); + + if (isUnexpectedResult) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Crc32)}.{nameof(Crc32.ComputeCrc32C)}(UInt32, Byte): ComputeCrc32C failed:"); + TestLibrary.TestFramework.LogInformation($" left: {left}"); + TestLibrary.TestFramework.LogInformation($" right: {right}"); + TestLibrary.TestFramework.LogInformation($" result: {result}"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32C.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32C.UInt16.cs new file mode 100644 index 00000000000000..2ec74ccb995039 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32C.UInt16.cs @@ -0,0 +1,242 @@ +// 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 ComputeCrc32C_UInt16() + { + var test = new ScalarBinaryOpTest__ComputeCrc32C_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ScalarBinaryOpTest__ComputeCrc32C_UInt16 + { + private struct TestStruct + { + public UInt32 _fld1; + public UInt16 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + testStruct._fld1 = 0xFFFFFFFF; + testStruct._fld2 = 0x2019; + + return testStruct; + } + + public void RunStructFldScenario(ScalarBinaryOpTest__ComputeCrc32C_UInt16 testClass) + { + var result = Crc32.ComputeCrc32C(_fld1, _fld2); + testClass.ValidateResult(_fld1, _fld2, result); + } + } + + private static UInt32 _data1; + private static UInt16 _data2; + + private static UInt32 _clsVar1; + private static UInt16 _clsVar2; + + private UInt32 _fld1; + private UInt16 _fld2; + + static ScalarBinaryOpTest__ComputeCrc32C_UInt16() + { + _clsVar1 = 0xFFFFFFFF; + _clsVar2 = 0x2019; + } + + public ScalarBinaryOpTest__ComputeCrc32C_UInt16() + { + Succeeded = true; + + _fld1 = 0xFFFFFFFF; + _fld2 = 0x2019; + + _data1 = 0xFFFFFFFF; + _data2 = 0x2019; + } + + public bool IsSupported => Crc32.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Crc32.ComputeCrc32C( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + ); + + ValidateResult(_data1, _data2, result); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Crc32).GetMethod(nameof(Crc32.ComputeCrc32C), new Type[] { typeof(UInt32), typeof(UInt16) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + }); + + ValidateResult(_data1, _data2, (UInt32)result); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Crc32.ComputeCrc32C( + _clsVar1, + _clsVar2 + ); + + ValidateResult(_clsVar1, _clsVar2, result); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data1 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)); + var data2 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)); + var result = Crc32.ComputeCrc32C(data1, data2); + + ValidateResult(data1, data2, result); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ScalarBinaryOpTest__ComputeCrc32C_UInt16(); + var result = Crc32.ComputeCrc32C(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Crc32.ComputeCrc32C(_fld1, _fld2); + ValidateResult(_fld1, _fld2, result); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Crc32.ComputeCrc32C(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(UInt32 left, UInt16 right, UInt32 result, [CallerMemberName] string method = "") + { + var isUnexpectedResult = false; + + uint expectedResult = 0x9F50ACBD; isUnexpectedResult = (expectedResult != result); + + if (isUnexpectedResult) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Crc32)}.{nameof(Crc32.ComputeCrc32C)}(UInt32, UInt16): ComputeCrc32C failed:"); + TestLibrary.TestFramework.LogInformation($" left: {left}"); + TestLibrary.TestFramework.LogInformation($" right: {right}"); + TestLibrary.TestFramework.LogInformation($" result: {result}"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32C.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32C.UInt32.cs new file mode 100644 index 00000000000000..be2c4be03ddbea --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/ComputeCrc32C.UInt32.cs @@ -0,0 +1,242 @@ +// 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 ComputeCrc32C_UInt32() + { + var test = new ScalarBinaryOpTest__ComputeCrc32C_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ScalarBinaryOpTest__ComputeCrc32C_UInt32 + { + private struct TestStruct + { + public UInt32 _fld1; + public UInt32 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + testStruct._fld1 = 0xFFFFFFFF; + testStruct._fld2 = 0x20191113; + + return testStruct; + } + + public void RunStructFldScenario(ScalarBinaryOpTest__ComputeCrc32C_UInt32 testClass) + { + var result = Crc32.ComputeCrc32C(_fld1, _fld2); + testClass.ValidateResult(_fld1, _fld2, result); + } + } + + private static UInt32 _data1; + private static UInt32 _data2; + + private static UInt32 _clsVar1; + private static UInt32 _clsVar2; + + private UInt32 _fld1; + private UInt32 _fld2; + + static ScalarBinaryOpTest__ComputeCrc32C_UInt32() + { + _clsVar1 = 0xFFFFFFFF; + _clsVar2 = 0x20191113; + } + + public ScalarBinaryOpTest__ComputeCrc32C_UInt32() + { + Succeeded = true; + + _fld1 = 0xFFFFFFFF; + _fld2 = 0x20191113; + + _data1 = 0xFFFFFFFF; + _data2 = 0x20191113; + } + + public bool IsSupported => Crc32.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Crc32.ComputeCrc32C( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + ); + + ValidateResult(_data1, _data2, result); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Crc32).GetMethod(nameof(Crc32.ComputeCrc32C), new Type[] { typeof(UInt32), typeof(UInt32) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)), + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)) + }); + + ValidateResult(_data1, _data2, (UInt32)result); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Crc32.ComputeCrc32C( + _clsVar1, + _clsVar2 + ); + + ValidateResult(_clsVar1, _clsVar2, result); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data1 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data1)); + var data2 = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data2)); + var result = Crc32.ComputeCrc32C(data1, data2); + + ValidateResult(data1, data2, result); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ScalarBinaryOpTest__ComputeCrc32C_UInt32(); + var result = Crc32.ComputeCrc32C(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Crc32.ComputeCrc32C(_fld1, _fld2); + ValidateResult(_fld1, _fld2, result); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Crc32.ComputeCrc32C(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(UInt32 left, UInt32 right, UInt32 result, [CallerMemberName] string method = "") + { + var isUnexpectedResult = false; + + uint expectedResult = 0x78F34758; isUnexpectedResult = (expectedResult != result); + + if (isUnexpectedResult) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Crc32)}.{nameof(Crc32.ComputeCrc32C)}(UInt32, UInt32): ComputeCrc32C failed:"); + TestLibrary.TestFramework.LogInformation($" left: {left}"); + TestLibrary.TestFramework.LogInformation($" right: {right}"); + TestLibrary.TestFramework.LogInformation($" result: {result}"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/Crc32_r.csproj b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/Crc32_r.csproj new file mode 100644 index 00000000000000..8282fd8c6776db --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/Crc32_r.csproj @@ -0,0 +1,21 @@ + + + Exe + true + + + Embedded + + + + + + + + + + + + + + diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/Crc32_ro.csproj b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/Crc32_ro.csproj new file mode 100644 index 00000000000000..3b241660e5e16b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/Crc32_ro.csproj @@ -0,0 +1,21 @@ + + + Exe + true + + + Embedded + True + + + + + + + + + + + + + diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/Program.Crc32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/Program.Crc32.cs new file mode 100644 index 00000000000000..1721ccd77079d3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Crc32/Program.Crc32.cs @@ -0,0 +1,24 @@ +// 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. + +using System; +using System.Collections.Generic; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + static Program() + { + TestList = new Dictionary() { + ["ComputeCrc32.Byte"] = ComputeCrc32_Byte, + ["ComputeCrc32.UInt16"] = ComputeCrc32_UInt16, + ["ComputeCrc32.UInt32"] = ComputeCrc32_UInt32, + ["ComputeCrc32C.Byte"] = ComputeCrc32C_Byte, + ["ComputeCrc32C.UInt16"] = ComputeCrc32C_UInt16, + ["ComputeCrc32C.UInt32"] = ComputeCrc32C_UInt32, + }; + } + } +} 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 e040ffb138b11d..4b3a4ff55d42b5 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx @@ -140,6 +140,22 @@ private static readonly (string templateFileName, Dictionary tem ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_UInt64", ["Isa"] = "ArmBase.Arm64", ["Method"] = "LeadingZeroCount", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "int expectedResult = 0; for (int index = 63; ((data >> index) & 1) == 0; index--) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }), }; +private static readonly (string templateFileName, Dictionary templateData)[] Crc32Inputs = new [] +{ + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32_Byte", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20", ["ValidateResult"] = "uint expectedResult = 0x169330BA; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32_UInt16", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x2019", ["ValidateResult"] = "uint expectedResult = 0x1E4864D0; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32_UInt32", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20191113", ["ValidateResult"] = "uint expectedResult = 0x219D9805; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32C_Byte", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32C", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20", ["ValidateResult"] = "uint expectedResult = 0x8D3F2270; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32C_UInt16", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32C", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x2019", ["ValidateResult"] = "uint expectedResult = 0x9F50ACBD; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32C_UInt32", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32C", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20191113", ["ValidateResult"] = "uint expectedResult = 0x78F34758; isUnexpectedResult = (expectedResult != result);" }), +}; + +private static readonly (string templateFileName, Dictionary templateData)[] Crc32_Arm64Inputs = new [] +{ + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32_UInt64", ["Isa"] = "Crc32.Arm64", ["Method"] = "ComputeCrc32", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20191113110219UL", ["ValidateResult"] = "uint expectedResult = 0xEFAAAB74; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32C_UInt64", ["Isa"] = "Crc32.Arm64", ["Method"] = "ComputeCrc32C", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20191113110219UL", ["ValidateResult"] = "uint expectedResult = 0x6295C71A; isUnexpectedResult = (expectedResult != result);" }), +}; + private static void ProcessInputs(string groupName, (string templateFileName, Dictionary templateData)[] inputs) { var directoryName = Path.Combine("..", groupName); @@ -258,3 +274,5 @@ ProcessInputs("AdvSimd.Arm64", AdvSimd_Arm64Inputs); ProcessInputs("Aes", AesInputs); ProcessInputs("ArmBase", ArmBaseInputs); ProcessInputs("ArmBase.Arm64", ArmBase_Arm64Inputs); +ProcessInputs("Crc32", Crc32Inputs); +ProcessInputs("Crc32.Arm64", Crc32_Arm64Inputs); \ No newline at end of file diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Program.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Program.cs index b30089fbbe79ed..e03d0a4b0b3ec2 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Program.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Program.cs @@ -73,6 +73,7 @@ private static void PrintSupportedIsa() TestLibrary.TestFramework.LogInformation($" AdvSimd: {AdvSimd.IsSupported}"); TestLibrary.TestFramework.LogInformation($" Aes: {Aes.IsSupported}"); TestLibrary.TestFramework.LogInformation($" ArmBase: {ArmBase.IsSupported}"); + TestLibrary.TestFramework.LogInformation($" Crc32: {Crc32.IsSupported}"); TestLibrary.TestFramework.LogInformation($" Sha1: {Sha1.IsSupported}"); TestLibrary.TestFramework.LogInformation($" Sha256: {Sha256.IsSupported}"); TestLibrary.TestFramework.LogInformation(string.Empty); From 54684e8d200bc1b60064a1054edafdf0acac18e7 Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Wed, 13 Nov 2019 15:32:20 -0800 Subject: [PATCH 9/9] Make LeadingZeroCount and LeadingSignCount as HW_Flag_BaseTypeFromFirstArg in jit/hwintrinsiclistarm64.h --- src/coreclr/src/jit/hwintrinsiclistarm64.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/src/jit/hwintrinsiclistarm64.h b/src/coreclr/src/jit/hwintrinsiclistarm64.h index 1f568e9fb3f60a..e8e34aef867661 100644 --- a/src/coreclr/src/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/src/jit/hwintrinsiclistarm64.h @@ -82,15 +82,15 @@ HARDWARE_INTRINSIC(Aes, MixColumns, - // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Base Intrinsics -HARDWARE_INTRINSIC(ArmBase, LeadingZeroCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment) +HARDWARE_INTRINSIC(ArmBase, LeadingZeroCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name ival SIMD size NumArg instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Base 64-bit only Intrinsics -HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingSignCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment) -HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingZeroCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment) +HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingSignCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingZeroCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name ival SIMD size NumArg instructions Category Flags