From 2a3bfd5ffb2396e5dd225716df6ddbae40578e9e Mon Sep 17 00:00:00 2001 From: "Canino, Anthony" Date: Mon, 9 May 2022 05:55:01 -0700 Subject: [PATCH] Add X86Serialize hardware intrinsic. --- src/coreclr/inc/clrconfigvalues.h | 1 + src/coreclr/inc/corinfoinstructionset.h | 94 +++++++++------- src/coreclr/inc/jiteeversionguid.h | 10 +- src/coreclr/inc/readytoruninstructionset.h | 1 + src/coreclr/jit/codegen.h | 1 + src/coreclr/jit/compiler.h | 2 + src/coreclr/jit/emit.h | 1 + src/coreclr/jit/emitxarch.cpp | 8 +- src/coreclr/jit/hwintrinsiccodegenxarch.cpp | 34 ++++++ src/coreclr/jit/hwintrinsiclistxarch.h | 8 ++ src/coreclr/jit/hwintrinsicxarch.cpp | 36 +++++++ src/coreclr/jit/instrsxarch.h | 2 + .../Runtime/ReadyToRunInstructionSet.cs | 1 + .../Runtime/ReadyToRunInstructionSetHelper.cs | 4 + .../JitInterface/CorInfoInstructionSet.cs | 100 +++++++++++------- .../ThunkGenerator/InstructionSetDesc.txt | 3 + src/coreclr/vm/codeman.cpp | 10 ++ .../ILLink.Substitutions.NoX86Intrinsics.xml | 7 ++ .../System.Private.CoreLib.Shared.projitems | 2 + .../X86/X86Serialize.PlatformNotSupported.cs | 33 ++++++ .../Runtime/Intrinsics/X86/X86Serialize.cs | 34 ++++++ .../ref/System.Runtime.Intrinsics.cs | 14 +++ src/mono/mono/mini/simd-intrinsics.c | 1 + .../HardwareIntrinsics/X86/Shared/Program.cs | 1 + .../X86/X86Serialize/Serialize.cs | 34 ++++++ .../X86/X86Serialize/Serialize_r.csproj | 13 +++ .../X86/X86Serialize/Serialize_ro.csproj | 13 +++ .../X86/X86Serialize_X64/Serialize.X64.cs | 34 ++++++ .../X86Serialize_X64/Serialize.X64_r.csproj | 13 +++ .../X86Serialize_X64/Serialize.X64_ro.csproj | 13 +++ 30 files changed, 450 insertions(+), 78 deletions(-) create mode 100644 src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Serialize.PlatformNotSupported.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Serialize.cs create mode 100644 src/tests/JIT/HardwareIntrinsics/X86/X86Serialize/Serialize.cs create mode 100644 src/tests/JIT/HardwareIntrinsics/X86/X86Serialize/Serialize_r.csproj create mode 100644 src/tests/JIT/HardwareIntrinsics/X86/X86Serialize/Serialize_ro.csproj create mode 100644 src/tests/JIT/HardwareIntrinsics/X86/X86Serialize_X64/Serialize.X64.cs create mode 100644 src/tests/JIT/HardwareIntrinsics/X86/X86Serialize_X64/Serialize.X64_r.csproj create mode 100644 src/tests/JIT/HardwareIntrinsics/X86/X86Serialize_X64/Serialize.X64_ro.csproj diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index b7e27497739ef..2ab6a5f32e61c 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -766,6 +766,7 @@ RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableSSE3_4, W("EnableSSE3_4"), 1 RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableSSE41, W("EnableSSE41"), 1, "Allows SSE4.1+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableSSE42, W("EnableSSE42"), 1, "Allows SSE4.2+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableSSSE3, W("EnableSSSE3"), 1, "Allows SSSE3+ hardware intrinsics to be disabled") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableX86Serialize, W("EnableX86Serialize"), 1, "Allows X86Serialize+ hardware intrinsics to be disabled") #elif defined(TARGET_ARM64) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64AdvSimd, W("EnableArm64AdvSimd"), 1, "Allows Arm64 AdvSimd+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Aes, W("EnableArm64Aes"), 1, "Allows Arm64 Aes+ hardware intrinsics to be disabled") diff --git a/src/coreclr/inc/corinfoinstructionset.h b/src/coreclr/inc/corinfoinstructionset.h index 778b1839e4afb..3a818a8722bf9 100644 --- a/src/coreclr/inc/corinfoinstructionset.h +++ b/src/coreclr/inc/corinfoinstructionset.h @@ -59,24 +59,26 @@ enum CORINFO_InstructionSet InstructionSet_Vector256=18, InstructionSet_AVXVNNI=19, InstructionSet_MOVBE=20, - InstructionSet_X86Base_X64=21, - InstructionSet_SSE_X64=22, - InstructionSet_SSE2_X64=23, - InstructionSet_SSE3_X64=24, - InstructionSet_SSSE3_X64=25, - InstructionSet_SSE41_X64=26, - InstructionSet_SSE42_X64=27, - InstructionSet_AVX_X64=28, - InstructionSet_AVX2_X64=29, - InstructionSet_AES_X64=30, - InstructionSet_BMI1_X64=31, - InstructionSet_BMI2_X64=32, - InstructionSet_FMA_X64=33, - InstructionSet_LZCNT_X64=34, - InstructionSet_PCLMULQDQ_X64=35, - InstructionSet_POPCNT_X64=36, - InstructionSet_AVXVNNI_X64=37, - InstructionSet_MOVBE_X64=38, + InstructionSet_X86Serialize=21, + InstructionSet_X86Base_X64=22, + InstructionSet_SSE_X64=23, + InstructionSet_SSE2_X64=24, + InstructionSet_SSE3_X64=25, + InstructionSet_SSSE3_X64=26, + InstructionSet_SSE41_X64=27, + InstructionSet_SSE42_X64=28, + InstructionSet_AVX_X64=29, + InstructionSet_AVX2_X64=30, + InstructionSet_AES_X64=31, + InstructionSet_BMI1_X64=32, + InstructionSet_BMI2_X64=33, + InstructionSet_FMA_X64=34, + InstructionSet_LZCNT_X64=35, + InstructionSet_PCLMULQDQ_X64=36, + InstructionSet_POPCNT_X64=37, + InstructionSet_AVXVNNI_X64=38, + InstructionSet_MOVBE_X64=39, + InstructionSet_X86Serialize_X64=40, #endif // TARGET_AMD64 #ifdef TARGET_X86 InstructionSet_X86Base=1, @@ -99,24 +101,26 @@ enum CORINFO_InstructionSet InstructionSet_Vector256=18, InstructionSet_AVXVNNI=19, InstructionSet_MOVBE=20, - InstructionSet_X86Base_X64=21, - InstructionSet_SSE_X64=22, - InstructionSet_SSE2_X64=23, - InstructionSet_SSE3_X64=24, - InstructionSet_SSSE3_X64=25, - InstructionSet_SSE41_X64=26, - InstructionSet_SSE42_X64=27, - InstructionSet_AVX_X64=28, - InstructionSet_AVX2_X64=29, - InstructionSet_AES_X64=30, - InstructionSet_BMI1_X64=31, - InstructionSet_BMI2_X64=32, - InstructionSet_FMA_X64=33, - InstructionSet_LZCNT_X64=34, - InstructionSet_PCLMULQDQ_X64=35, - InstructionSet_POPCNT_X64=36, - InstructionSet_AVXVNNI_X64=37, - InstructionSet_MOVBE_X64=38, + InstructionSet_X86Serialize=21, + InstructionSet_X86Base_X64=22, + InstructionSet_SSE_X64=23, + InstructionSet_SSE2_X64=24, + InstructionSet_SSE3_X64=25, + InstructionSet_SSSE3_X64=26, + InstructionSet_SSE41_X64=27, + InstructionSet_SSE42_X64=28, + InstructionSet_AVX_X64=29, + InstructionSet_AVX2_X64=30, + InstructionSet_AES_X64=31, + InstructionSet_BMI1_X64=32, + InstructionSet_BMI2_X64=33, + InstructionSet_FMA_X64=34, + InstructionSet_LZCNT_X64=35, + InstructionSet_PCLMULQDQ_X64=36, + InstructionSet_POPCNT_X64=37, + InstructionSet_AVXVNNI_X64=38, + InstructionSet_MOVBE_X64=39, + InstructionSet_X86Serialize_X64=40, #endif // TARGET_X86 }; @@ -218,6 +222,8 @@ struct CORINFO_InstructionSetFlags AddInstructionSet(InstructionSet_AVXVNNI_X64); if (HasInstructionSet(InstructionSet_MOVBE)) AddInstructionSet(InstructionSet_MOVBE_X64); + if (HasInstructionSet(InstructionSet_X86Serialize)) + AddInstructionSet(InstructionSet_X86Serialize_X64); #endif // TARGET_AMD64 #ifdef TARGET_X86 #endif // TARGET_X86 @@ -367,6 +373,10 @@ inline CORINFO_InstructionSetFlags EnsureInstructionSetFlagsAreValid(CORINFO_Ins resultflags.RemoveInstructionSet(InstructionSet_MOVBE); if (resultflags.HasInstructionSet(InstructionSet_MOVBE_X64) && !resultflags.HasInstructionSet(InstructionSet_MOVBE)) resultflags.RemoveInstructionSet(InstructionSet_MOVBE_X64); + if (resultflags.HasInstructionSet(InstructionSet_X86Serialize) && !resultflags.HasInstructionSet(InstructionSet_X86Serialize_X64)) + resultflags.RemoveInstructionSet(InstructionSet_X86Serialize); + if (resultflags.HasInstructionSet(InstructionSet_X86Serialize_X64) && !resultflags.HasInstructionSet(InstructionSet_X86Serialize)) + resultflags.RemoveInstructionSet(InstructionSet_X86Serialize_X64); if (resultflags.HasInstructionSet(InstructionSet_SSE) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) resultflags.RemoveInstructionSet(InstructionSet_SSE); if (resultflags.HasInstructionSet(InstructionSet_SSE2) && !resultflags.HasInstructionSet(InstructionSet_SSE)) @@ -405,6 +415,8 @@ inline CORINFO_InstructionSetFlags EnsureInstructionSetFlagsAreValid(CORINFO_Ins resultflags.RemoveInstructionSet(InstructionSet_AVXVNNI); if (resultflags.HasInstructionSet(InstructionSet_MOVBE) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) resultflags.RemoveInstructionSet(InstructionSet_MOVBE); + if (resultflags.HasInstructionSet(InstructionSet_X86Serialize) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) + resultflags.RemoveInstructionSet(InstructionSet_X86Serialize); #endif // TARGET_AMD64 #ifdef TARGET_X86 if (resultflags.HasInstructionSet(InstructionSet_SSE) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) @@ -445,6 +457,8 @@ inline CORINFO_InstructionSetFlags EnsureInstructionSetFlagsAreValid(CORINFO_Ins resultflags.RemoveInstructionSet(InstructionSet_AVXVNNI); if (resultflags.HasInstructionSet(InstructionSet_MOVBE) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) resultflags.RemoveInstructionSet(InstructionSet_MOVBE); + if (resultflags.HasInstructionSet(InstructionSet_X86Serialize) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) + resultflags.RemoveInstructionSet(InstructionSet_X86Serialize); #endif // TARGET_X86 } while (!oldflags.Equals(resultflags)); @@ -581,6 +595,10 @@ inline const char *InstructionSetToString(CORINFO_InstructionSet instructionSet) return "MOVBE"; case InstructionSet_MOVBE_X64 : return "MOVBE_X64"; + case InstructionSet_X86Serialize : + return "X86Serialize"; + case InstructionSet_X86Serialize_X64 : + return "X86Serialize_X64"; #endif // TARGET_AMD64 #ifdef TARGET_X86 case InstructionSet_X86Base : @@ -623,6 +641,8 @@ inline const char *InstructionSetToString(CORINFO_InstructionSet instructionSet) return "AVXVNNI"; case InstructionSet_MOVBE : return "MOVBE"; + case InstructionSet_X86Serialize : + return "X86Serialize"; #endif // TARGET_X86 default: @@ -673,6 +693,7 @@ inline CORINFO_InstructionSet InstructionSetFromR2RInstructionSet(ReadyToRunInst case READYTORUN_INSTRUCTION_Popcnt: return InstructionSet_POPCNT; case READYTORUN_INSTRUCTION_AvxVnni: return InstructionSet_AVXVNNI; case READYTORUN_INSTRUCTION_Movbe: return InstructionSet_MOVBE; + case READYTORUN_INSTRUCTION_X86Serialize: return InstructionSet_X86Serialize; #endif // TARGET_AMD64 #ifdef TARGET_X86 case READYTORUN_INSTRUCTION_X86Base: return InstructionSet_X86Base; @@ -693,6 +714,7 @@ inline CORINFO_InstructionSet InstructionSetFromR2RInstructionSet(ReadyToRunInst case READYTORUN_INSTRUCTION_Popcnt: return InstructionSet_POPCNT; case READYTORUN_INSTRUCTION_AvxVnni: return InstructionSet_AVXVNNI; case READYTORUN_INSTRUCTION_Movbe: return InstructionSet_MOVBE; + case READYTORUN_INSTRUCTION_X86Serialize: return InstructionSet_X86Serialize; #endif // TARGET_X86 default: diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index ce062f5e082b1..016c08df880d1 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* dfda4767-9618-4d6a-8105-a86034dc52eb */ - 0xdfda4767, - 0x9618, - 0x4d6a, - {0x81, 0x05, 0xa8, 0x60, 0x34, 0xdc, 0x52, 0xeb} +constexpr GUID JITEEVersionIdentifier = { /* f2a217c4-2a69-4308-99ce-8292c6763776 */ + 0xf2a217c4, + 0x2a69, + 0x4308, + {0x99, 0xce, 0x82, 0x92, 0xc6, 0x76, 0x37, 0x76} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/inc/readytoruninstructionset.h b/src/coreclr/inc/readytoruninstructionset.h index 62935f58668d6..658d66b806d99 100644 --- a/src/coreclr/inc/readytoruninstructionset.h +++ b/src/coreclr/inc/readytoruninstructionset.h @@ -36,6 +36,7 @@ enum ReadyToRunInstructionSet READYTORUN_INSTRUCTION_AvxVnni=25, READYTORUN_INSTRUCTION_Rcpc=26, READYTORUN_INSTRUCTION_Movbe=27, + READYTORUN_INSTRUCTION_X86Serialize=28, }; diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index 722503cd5260c..4c0c78a3a03b2 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -1131,6 +1131,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void genPCLMULQDQIntrinsic(GenTreeHWIntrinsic* node); void genPOPCNTIntrinsic(GenTreeHWIntrinsic* node); void genXCNTIntrinsic(GenTreeHWIntrinsic* node, instruction ins); + void genX86SerializeIntrinsic(GenTreeHWIntrinsic* node); template void genHWIntrinsicJumpTableFallback(NamedIntrinsic intrinsic, regNumber nonConstImmReg, diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 7d79862592ffe..ee8e00b27b1f4 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -3737,6 +3737,8 @@ class Compiler GenTree* impSSE2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig); GenTree* impAvxOrAvx2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig); GenTree* impBMI1OrBMI2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig); + + GenTree* impSerializeIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig); #endif // TARGET_XARCH #endif // FEATURE_HW_INTRINSICS GenTree* impArrayAccessIntrinsic(CORINFO_CLASS_HANDLE clsHnd, diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 777cfdf18b945..d981f5b4e6399 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -1386,6 +1386,7 @@ class emitter #define PERFSCORE_THROUGHPUT_19C 19.0f // slower - 19 cycles #define PERFSCORE_THROUGHPUT_25C 25.0f // slower - 25 cycles #define PERFSCORE_THROUGHPUT_33C 33.0f // slower - 33 cycles +#define PERFSCORE_THROUGHPUT_50C 50.0f // slower - 50 cycles #define PERFSCORE_THROUGHPUT_52C 52.0f // slower - 52 cycles #define PERFSCORE_THROUGHPUT_57C 57.0f // slower - 57 cycles #define PERFSCORE_THROUGHPUT_140C 140.0f // slower - 140 cycles diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 85fd285399bd9..ebe6030a8d709 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -2952,7 +2952,7 @@ void emitter::emitIns(instruction ins) ins == INS_sahf || ins == INS_stosb || ins == INS_stosd || ins == INS_stosp // These instructions take zero operands || ins == INS_vzeroupper || ins == INS_lfence || ins == INS_mfence || ins == INS_sfence || - ins == INS_pause); + ins == INS_pause || ins == INS_serialize); assert(assertCond); } @@ -16317,6 +16317,12 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins } break; + case INS_serialize: + { + result.insThroughput = PERFSCORE_THROUGHPUT_50C; + break; + } + default: // unhandled instruction insFmt combination perfScoreUnhandledInstruction(id, &result); diff --git a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp index 094325a4ca4ee..42b20cea7e2be 100644 --- a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp @@ -427,6 +427,11 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) case InstructionSet_POPCNT_X64: genPOPCNTIntrinsic(node); break; + case InstructionSet_X86Serialize: + case InstructionSet_X86Serialize_X64: + genX86SerializeIntrinsic(node); + break; + default: unreached(); break; @@ -1957,4 +1962,33 @@ void CodeGen::genXCNTIntrinsic(GenTreeHWIntrinsic* node, instruction ins) genHWIntrinsic_R_RM(node, ins, emitTypeSize(node->TypeGet()), targetReg, op1); } +//------------------------------------------------------------------------ +// genX86SerializeIntrinsic: Generates the code for an X86 serialize hardware intrinsic node +// +// Arguments: +// node - The hardware intrinsic node +// +void CodeGen::genX86SerializeIntrinsic(GenTreeHWIntrinsic* node) +{ + NamedIntrinsic intrinsicId = node->GetHWIntrinsicId(); + + genConsumeMultiOpOperands(node); + + switch (intrinsicId) + { + case NI_X86Serialize_Serialize: + { + assert(node->GetSimdBaseType() == TYP_UNKNOWN); + GetEmitter()->emitIns(INS_serialize); + break; + } + + default: + unreached(); + break; + } + + genProduceReg(node); +} + #endif // FEATURE_HW_INTRINSICS diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h index 22c85d758e3b6..2b04842455775 100644 --- a/src/coreclr/jit/hwintrinsiclistxarch.h +++ b/src/coreclr/jit/hwintrinsiclistxarch.h @@ -813,6 +813,14 @@ HARDWARE_INTRINSIC(POPCNT, PopCount, // POPCNT Intrinsics HARDWARE_INTRINSIC(POPCNT_X64, PopCount, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_popcnt, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics|HW_Flag_MultiIns) +// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +// ISA Function name 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} +// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +// X86Serialize Intrinsics +HARDWARE_INTRINSIC(X86Serialize, Serialize, 0, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) + + // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name 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} diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp index c425ffdd9e150..d48db6661c941 100644 --- a/src/coreclr/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/jit/hwintrinsicxarch.cpp @@ -52,6 +52,8 @@ static CORINFO_InstructionSet X64VersionOfIsa(CORINFO_InstructionSet isa) return InstructionSet_PCLMULQDQ_X64; case InstructionSet_POPCNT: return InstructionSet_POPCNT_X64; + case InstructionSet_X86Serialize: + return InstructionSet_X86Serialize_X64; default: return InstructionSet_NONE; } @@ -159,6 +161,10 @@ static CORINFO_InstructionSet lookupInstructionSet(const char* className) { return InstructionSet_X86Base; } + else if (strcmp(className, "X86Serialize") == 0) + { + return InstructionSet_X86Serialize; + } return InstructionSet_ILLEGAL; } @@ -384,6 +390,8 @@ bool HWIntrinsicInfo::isFullyImplementedIsa(CORINFO_InstructionSet isa) case InstructionSet_Vector256: case InstructionSet_X86Base: case InstructionSet_X86Base_X64: + case InstructionSet_X86Serialize: + case InstructionSet_X86Serialize_X64: { return true; } @@ -506,6 +514,11 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case InstructionSet_BMI2: case InstructionSet_BMI2_X64: return impBMI1OrBMI2Intrinsic(intrinsic, method, sig); + + case InstructionSet_X86Serialize: + case InstructionSet_X86Serialize_X64: + return impSerializeIntrinsic(intrinsic, method, sig); + default: return nullptr; } @@ -2282,6 +2295,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, } case NI_X86Base_Pause: + case NI_X86Serialize_Serialize: { assert(sig->numArgs == 0); assert(JITtype2varType(sig->retType) == TYP_VOID); @@ -2566,4 +2580,26 @@ GenTree* Compiler::impBMI1OrBMI2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METH } } +GenTree* Compiler::impSerializeIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig) +{ + GenTree* retNode = nullptr; + + switch (intrinsic) + { + case NI_X86Serialize_Serialize: + { + assert(sig->numArgs == 0); + assert(JITtype2varType(sig->retType) == TYP_VOID); + + retNode = gtNewScalarHWIntrinsicNode(TYP_VOID, intrinsic); + break; + } + + default: + return nullptr; + } + + return retNode; +} + #endif // FEATURE_HW_INTRINSICS diff --git a/src/coreclr/jit/instrsxarch.h b/src/coreclr/jit/instrsxarch.h index e08667e87a9f5..5a626ce26e96e 100644 --- a/src/coreclr/jit/instrsxarch.h +++ b/src/coreclr/jit/instrsxarch.h @@ -683,6 +683,8 @@ INST1(pause, "pause", IUM_RD, 0x0090F3, INST1(lock, "lock", IUM_RD, 0x0000F0, INS_FLAGS_None ) INST1(leave, "leave", IUM_RD, 0x0000C9, INS_FLAGS_None ) +INST1(serialize, "serialize", IUM_RD, 0x0fe801, INS_FLAGS_None ) + INST1(neg, "neg", IUM_RW, 0x0018F6, Writes_OF | Writes_SF | Writes_ZF | Writes_AF | Writes_PF | Writes_CF | INS_FLAGS_Has_Wbit ) INST1(not, "not", IUM_RW, 0x0010F6, INS_FLAGS_None | INS_FLAGS_Has_Wbit ) diff --git a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs index 1157bf84edf4e..f7e1bb55a9b79 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs @@ -39,6 +39,7 @@ public enum ReadyToRunInstructionSet AvxVnni=25, Rcpc=26, Movbe=27, + X86Serialize=28, } } diff --git a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSetHelper.cs b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSetHelper.cs index 69c29c7f96070..bde3aac7b4160 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSetHelper.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSetHelper.cs @@ -91,6 +91,8 @@ public static class ReadyToRunInstructionSetHelper case InstructionSet.X64_AVXVNNI_X64: return ReadyToRunInstructionSet.AvxVnni; case InstructionSet.X64_MOVBE: return ReadyToRunInstructionSet.Movbe; case InstructionSet.X64_MOVBE_X64: return ReadyToRunInstructionSet.Movbe; + case InstructionSet.X64_X86Serialize: return ReadyToRunInstructionSet.X86Serialize; + case InstructionSet.X64_X86Serialize_X64: return ReadyToRunInstructionSet.X86Serialize; default: throw new Exception("Unknown instruction set"); } @@ -138,6 +140,8 @@ public static class ReadyToRunInstructionSetHelper case InstructionSet.X86_AVXVNNI_X64: return null; case InstructionSet.X86_MOVBE: return ReadyToRunInstructionSet.Movbe; case InstructionSet.X86_MOVBE_X64: return null; + case InstructionSet.X86_X86Serialize: return ReadyToRunInstructionSet.X86Serialize; + case InstructionSet.X86_X86Serialize_X64: return null; default: throw new Exception("Unknown instruction set"); } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs b/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs index fc90274c415bf..8e82477d4f202 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs @@ -59,6 +59,7 @@ public enum InstructionSet X64_Vector256 = InstructionSet_X64.Vector256, X64_AVXVNNI = InstructionSet_X64.AVXVNNI, X64_MOVBE = InstructionSet_X64.MOVBE, + X64_X86Serialize = InstructionSet_X64.X86Serialize, X64_X86Base_X64 = InstructionSet_X64.X86Base_X64, X64_SSE_X64 = InstructionSet_X64.SSE_X64, X64_SSE2_X64 = InstructionSet_X64.SSE2_X64, @@ -77,6 +78,7 @@ public enum InstructionSet X64_POPCNT_X64 = InstructionSet_X64.POPCNT_X64, X64_AVXVNNI_X64 = InstructionSet_X64.AVXVNNI_X64, X64_MOVBE_X64 = InstructionSet_X64.MOVBE_X64, + X64_X86Serialize_X64 = InstructionSet_X64.X86Serialize_X64, X86_X86Base = InstructionSet_X86.X86Base, X86_SSE = InstructionSet_X86.SSE, X86_SSE2 = InstructionSet_X86.SSE2, @@ -97,6 +99,7 @@ public enum InstructionSet X86_Vector256 = InstructionSet_X86.Vector256, X86_AVXVNNI = InstructionSet_X86.AVXVNNI, X86_MOVBE = InstructionSet_X86.MOVBE, + X86_X86Serialize = InstructionSet_X86.X86Serialize, X86_X86Base_X64 = InstructionSet_X86.X86Base_X64, X86_SSE_X64 = InstructionSet_X86.SSE_X64, X86_SSE2_X64 = InstructionSet_X86.SSE2_X64, @@ -115,6 +118,7 @@ public enum InstructionSet X86_POPCNT_X64 = InstructionSet_X86.POPCNT_X64, X86_AVXVNNI_X64 = InstructionSet_X86.AVXVNNI_X64, X86_MOVBE_X64 = InstructionSet_X86.MOVBE_X64, + X86_X86Serialize_X64 = InstructionSet_X86.X86Serialize_X64, } public enum InstructionSet_ARM64 @@ -168,24 +172,26 @@ public enum InstructionSet_X64 Vector256 = 18, AVXVNNI = 19, MOVBE = 20, - X86Base_X64 = 21, - SSE_X64 = 22, - SSE2_X64 = 23, - SSE3_X64 = 24, - SSSE3_X64 = 25, - SSE41_X64 = 26, - SSE42_X64 = 27, - AVX_X64 = 28, - AVX2_X64 = 29, - AES_X64 = 30, - BMI1_X64 = 31, - BMI2_X64 = 32, - FMA_X64 = 33, - LZCNT_X64 = 34, - PCLMULQDQ_X64 = 35, - POPCNT_X64 = 36, - AVXVNNI_X64 = 37, - MOVBE_X64 = 38, + X86Serialize = 21, + X86Base_X64 = 22, + SSE_X64 = 23, + SSE2_X64 = 24, + SSE3_X64 = 25, + SSSE3_X64 = 26, + SSE41_X64 = 27, + SSE42_X64 = 28, + AVX_X64 = 29, + AVX2_X64 = 30, + AES_X64 = 31, + BMI1_X64 = 32, + BMI2_X64 = 33, + FMA_X64 = 34, + LZCNT_X64 = 35, + PCLMULQDQ_X64 = 36, + POPCNT_X64 = 37, + AVXVNNI_X64 = 38, + MOVBE_X64 = 39, + X86Serialize_X64 = 40, } public enum InstructionSet_X86 @@ -212,24 +218,26 @@ public enum InstructionSet_X86 Vector256 = 18, AVXVNNI = 19, MOVBE = 20, - X86Base_X64 = 21, - SSE_X64 = 22, - SSE2_X64 = 23, - SSE3_X64 = 24, - SSSE3_X64 = 25, - SSE41_X64 = 26, - SSE42_X64 = 27, - AVX_X64 = 28, - AVX2_X64 = 29, - AES_X64 = 30, - BMI1_X64 = 31, - BMI2_X64 = 32, - FMA_X64 = 33, - LZCNT_X64 = 34, - PCLMULQDQ_X64 = 35, - POPCNT_X64 = 36, - AVXVNNI_X64 = 37, - MOVBE_X64 = 38, + X86Serialize = 21, + X86Base_X64 = 22, + SSE_X64 = 23, + SSE2_X64 = 24, + SSE3_X64 = 25, + SSSE3_X64 = 26, + SSE41_X64 = 27, + SSE42_X64 = 28, + AVX_X64 = 29, + AVX2_X64 = 30, + AES_X64 = 31, + BMI1_X64 = 32, + BMI2_X64 = 33, + FMA_X64 = 34, + LZCNT_X64 = 35, + PCLMULQDQ_X64 = 36, + POPCNT_X64 = 37, + AVXVNNI_X64 = 38, + MOVBE_X64 = 39, + X86Serialize_X64 = 40, } public struct InstructionSetFlags : IEnumerable @@ -469,6 +477,10 @@ public static InstructionSetFlags ExpandInstructionSetByImplicationHelper(Target resultflags.AddInstructionSet(InstructionSet.X64_MOVBE_X64); if (resultflags.HasInstructionSet(InstructionSet.X64_MOVBE_X64)) resultflags.AddInstructionSet(InstructionSet.X64_MOVBE); + if (resultflags.HasInstructionSet(InstructionSet.X64_X86Serialize)) + resultflags.AddInstructionSet(InstructionSet.X64_X86Serialize_X64); + if (resultflags.HasInstructionSet(InstructionSet.X64_X86Serialize_X64)) + resultflags.AddInstructionSet(InstructionSet.X64_X86Serialize); if (resultflags.HasInstructionSet(InstructionSet.X64_SSE)) resultflags.AddInstructionSet(InstructionSet.X64_X86Base); if (resultflags.HasInstructionSet(InstructionSet.X64_SSE2)) @@ -507,6 +519,8 @@ public static InstructionSetFlags ExpandInstructionSetByImplicationHelper(Target resultflags.AddInstructionSet(InstructionSet.X64_AVX2); if (resultflags.HasInstructionSet(InstructionSet.X64_MOVBE)) resultflags.AddInstructionSet(InstructionSet.X64_SSE42); + if (resultflags.HasInstructionSet(InstructionSet.X64_X86Serialize)) + resultflags.AddInstructionSet(InstructionSet.X64_X86Base); break; case TargetArchitecture.X86: @@ -548,6 +562,8 @@ public static InstructionSetFlags ExpandInstructionSetByImplicationHelper(Target resultflags.AddInstructionSet(InstructionSet.X86_AVX2); if (resultflags.HasInstructionSet(InstructionSet.X86_MOVBE)) resultflags.AddInstructionSet(InstructionSet.X86_SSE42); + if (resultflags.HasInstructionSet(InstructionSet.X86_X86Serialize)) + resultflags.AddInstructionSet(InstructionSet.X86_X86Base); break; } } while (!oldflags.Equals(resultflags)); @@ -644,6 +660,8 @@ private static InstructionSetFlags ExpandInstructionSetByReverseImplicationHelpe resultflags.AddInstructionSet(InstructionSet.X64_AVXVNNI); if (resultflags.HasInstructionSet(InstructionSet.X64_MOVBE_X64)) resultflags.AddInstructionSet(InstructionSet.X64_MOVBE); + if (resultflags.HasInstructionSet(InstructionSet.X64_X86Serialize_X64)) + resultflags.AddInstructionSet(InstructionSet.X64_X86Serialize); if (resultflags.HasInstructionSet(InstructionSet.X64_X86Base)) resultflags.AddInstructionSet(InstructionSet.X64_SSE); if (resultflags.HasInstructionSet(InstructionSet.X64_SSE)) @@ -682,6 +700,8 @@ private static InstructionSetFlags ExpandInstructionSetByReverseImplicationHelpe resultflags.AddInstructionSet(InstructionSet.X64_AVXVNNI); if (resultflags.HasInstructionSet(InstructionSet.X64_SSE42)) resultflags.AddInstructionSet(InstructionSet.X64_MOVBE); + if (resultflags.HasInstructionSet(InstructionSet.X64_X86Base)) + resultflags.AddInstructionSet(InstructionSet.X64_X86Serialize); break; case TargetArchitecture.X86: @@ -723,6 +743,8 @@ private static InstructionSetFlags ExpandInstructionSetByReverseImplicationHelpe resultflags.AddInstructionSet(InstructionSet.X86_AVXVNNI); if (resultflags.HasInstructionSet(InstructionSet.X86_SSE42)) resultflags.AddInstructionSet(InstructionSet.X86_MOVBE); + if (resultflags.HasInstructionSet(InstructionSet.X86_X86Base)) + resultflags.AddInstructionSet(InstructionSet.X86_X86Serialize); break; } } while (!oldflags.Equals(resultflags)); @@ -788,6 +810,7 @@ public static IEnumerable ArchitectureToValidInstructionSets yield return new InstructionSetInfo("Vector256", "", InstructionSet.X64_Vector256, false); yield return new InstructionSetInfo("avxvnni", "AvxVnni", InstructionSet.X64_AVXVNNI, true); yield return new InstructionSetInfo("movbe", "Movbe", InstructionSet.X64_MOVBE, true); + yield return new InstructionSetInfo("serialize", "X86Serialize", InstructionSet.X64_X86Serialize, true); break; case TargetArchitecture.X86: @@ -811,6 +834,7 @@ public static IEnumerable ArchitectureToValidInstructionSets yield return new InstructionSetInfo("Vector256", "", InstructionSet.X86_Vector256, false); yield return new InstructionSetInfo("avxvnni", "AvxVnni", InstructionSet.X86_AVXVNNI, true); yield return new InstructionSetInfo("movbe", "Movbe", InstructionSet.X86_MOVBE, true); + yield return new InstructionSetInfo("serialize", "X86Serialize", InstructionSet.X86_X86Serialize, true); break; } } @@ -876,6 +900,8 @@ public void Set64BitInstructionSetVariants(TargetArchitecture architecture) AddInstructionSet(InstructionSet.X64_AVXVNNI_X64); if (HasInstructionSet(InstructionSet.X64_MOVBE)) AddInstructionSet(InstructionSet.X64_MOVBE_X64); + if (HasInstructionSet(InstructionSet.X64_X86Serialize)) + AddInstructionSet(InstructionSet.X64_X86Serialize_X64); break; case TargetArchitecture.X86: @@ -918,6 +944,7 @@ public void Set64BitInstructionSetVariantsUnconditionally(TargetArchitecture arc AddInstructionSet(InstructionSet.X64_POPCNT_X64); AddInstructionSet(InstructionSet.X64_AVXVNNI_X64); AddInstructionSet(InstructionSet.X64_MOVBE_X64); + AddInstructionSet(InstructionSet.X64_X86Serialize_X64); break; case TargetArchitecture.X86: @@ -939,6 +966,7 @@ public void Set64BitInstructionSetVariantsUnconditionally(TargetArchitecture arc AddInstructionSet(InstructionSet.X86_POPCNT_X64); AddInstructionSet(InstructionSet.X86_AVXVNNI_X64); AddInstructionSet(InstructionSet.X86_MOVBE_X64); + AddInstructionSet(InstructionSet.X86_X86Serialize_X64); break; } } diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt index f1db26c523556..bab454dd4dbe3 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt @@ -45,6 +45,7 @@ instructionset ,X86 , , , ,Vector128, instructionset ,X86 , , , ,Vector256, instructionset ,X86 ,AvxVnni , ,25 ,AVXVNNI ,avxvnni instructionset ,X86 ,Movbe , ,27 ,MOVBE ,movbe +instructionset ,X86 ,X86Serialize , ,28 ,X86Serialize ,serialize instructionset64bit,X86 ,X86Base instructionset64bit,X86 ,SSE @@ -64,6 +65,7 @@ instructionset64bit,X86 ,PCLMULQDQ instructionset64bit,X86 ,POPCNT instructionset64bit,X86 ,AVXVNNI instructionset64bit,X86 ,MOVBE +instructionset64bit,X86 ,X86Serialize vectorinstructionset,X86 ,Vector128 vectorinstructionset,X86 ,Vector256 @@ -87,6 +89,7 @@ implication ,X86 ,Vector128 ,SSE implication ,X86 ,Vector256 ,AVX implication ,X86 ,AVXVNNI ,AVX2 implication ,X86 ,MOVBE ,SSE42 +implication ,X86 ,X86Serialize, X86Base ; Definition of X64 instruction sets definearch ,X64 ,64Bit ,X64 diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index 4fda5dce33d3e..83bbbd56d0b97 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -1498,6 +1498,11 @@ void EEJitManager::SetCpuInfo() { CPUCompileFlags.Set(InstructionSet_BMI2); } + + if ((cpuidInfo[EDX] & (1 << 14)) != 0) + { + CPUCompileFlags.Set(InstructionSet_X86Serialize); // SERIALIZE + } } } @@ -1659,6 +1664,11 @@ void EEJitManager::SetCpuInfo() { CPUCompileFlags.Clear(InstructionSet_SSSE3); } + + if (!CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_EnableX86Serialize)) + { + CPUCompileFlags.Clear(InstructionSet_X86Serialize); + } #elif defined(TARGET_ARM64) if (!CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_EnableHWIntrinsic)) { diff --git a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoX86Intrinsics.xml b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoX86Intrinsics.xml index 50dababbb347c..859ceebde69d9 100644 --- a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoX86Intrinsics.xml +++ b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoX86Intrinsics.xml @@ -105,5 +105,12 @@ + + + + + + + diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 1a09997db8943..db7442f1cd244 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -2286,6 +2286,7 @@ + @@ -2305,6 +2306,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Serialize.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Serialize.PlatformNotSupported.cs new file mode 100644 index 0000000000000..d938175f5be39 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Serialize.PlatformNotSupported.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System.Runtime.Intrinsics.X86 +{ + /// + /// This class provides access to Intel SERIALIZE hardware instruction via intrinsics + /// + [CLSCompliant(false)] + public abstract class X86Serialize : X86Base + { + internal X86Serialize() { } + + public static new bool IsSupported { [Intrinsic] get => false; } + + [Intrinsic] + public new abstract class X64 : X86Base.X64 + { + internal X64() { } + + public static new bool IsSupported { [Intrinsic] get => false; } + } + + /// + /// void _serialize (void); + /// + public static void Serialize() { throw new PlatformNotSupportedException(); } + + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Serialize.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Serialize.cs new file mode 100644 index 0000000000000..db74132812a82 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Serialize.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System.Runtime.Intrinsics.X86 +{ + /// + /// This class provides access to Intel SERIALIZE hardware instruction via intrinsics + /// + [Intrinsic] + [CLSCompliant(false)] + public abstract class X86Serialize : X86Base + { + internal X86Serialize() { } + + public static new bool IsSupported { get => IsSupported; } + + [Intrinsic] + public new abstract class X64 : X86Base.X64 + { + internal X64() { } + + public static new bool IsSupported { get => IsSupported; } + } + + /// + /// void _serialize (void); + /// + public static void Serialize() => Serialize(); + + } +} 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 60b34a918dba9..a4d220cd60fcb 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -4794,4 +4794,18 @@ internal X64() { } public static bool IsSupported { get { throw null; } } } } + + [System.CLSCompliantAttribute(false)] + public abstract partial class X86Serialize : System.Runtime.Intrinsics.X86.X86Base + { + internal X86Serialize() { } + public static new bool IsSupported { get { throw null; } } + + public static void Serialize() { throw null; } + public new abstract partial class X64 : System.Runtime.Intrinsics.X86.X86Base.X64 + { + internal X64() { } + public static new bool IsSupported { get { throw null; } } + } + } } diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index 347a17c8bde81..8940ff32aac33 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -3338,6 +3338,7 @@ static const IntrinGroup supported_x86_intrinsics [] = { { "Sse42", MONO_CPU_X86_SSE42, sse42_methods, sizeof (sse42_methods) }, { "Ssse3", MONO_CPU_X86_SSSE3, ssse3_methods, sizeof (ssse3_methods) }, { "X86Base", 0, x86base_methods, sizeof (x86base_methods) }, + { "X86Serialize", 0, unsupported, sizeof (unsupported) }, }; static MonoInst* diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Shared/Program.cs b/src/tests/JIT/HardwareIntrinsics/X86/Shared/Program.cs index 8f7a79fdd95b1..22014a8f7590c 100644 --- a/src/tests/JIT/HardwareIntrinsics/X86/Shared/Program.cs +++ b/src/tests/JIT/HardwareIntrinsics/X86/Shared/Program.cs @@ -96,6 +96,7 @@ private static void PrintSupportedIsa() TestLibrary.TestFramework.LogInformation($" SSE4.1: {Sse41.IsSupported}"); TestLibrary.TestFramework.LogInformation($" SSE4.2: {Sse42.IsSupported}"); TestLibrary.TestFramework.LogInformation($" SSSE3: {Ssse3.IsSupported}"); + TestLibrary.TestFramework.LogInformation($" X86Serialize: {X86Serialize.IsSupported}"); TestLibrary.TestFramework.LogInformation(string.Empty); } diff --git a/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize/Serialize.cs b/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize/Serialize.cs new file mode 100644 index 0000000000000..89a91c2175c56 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize/Serialize.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace IntelHardwareIntrinsicTest +{ + class Program + { + const int Pass = 100; + const int Fail = 0; + + static unsafe int Main(string[] args) + { + int testResult = X86Serialize.IsSupported ? Pass : Fail; + + try + { + X86Serialize.Serialize(); + } + catch (Exception e) + { + testResult = (X86Serialize.IsSupported || (e is not PlatformNotSupportedException)) ? Fail : Pass; + } + + return testResult; + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize/Serialize_r.csproj b/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize/Serialize_r.csproj new file mode 100644 index 0000000000000..5fa4dc98fa415 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize/Serialize_r.csproj @@ -0,0 +1,13 @@ + + + Exe + true + + + Embedded + + + + + + diff --git a/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize/Serialize_ro.csproj b/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize/Serialize_ro.csproj new file mode 100644 index 0000000000000..e74cedfbe9e94 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize/Serialize_ro.csproj @@ -0,0 +1,13 @@ + + + Exe + true + + + Embedded + True + + + + + diff --git a/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize_X64/Serialize.X64.cs b/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize_X64/Serialize.X64.cs new file mode 100644 index 0000000000000..9665a0a7aa86e --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize_X64/Serialize.X64.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace IntelHardwareIntrinsicTest +{ + class Program + { + const int Pass = 100; + const int Fail = 0; + + static unsafe int Main(string[] args) + { + int testResult = X86Serialize.X64.IsSupported ? Pass : Fail; + + try + { + X86Serialize.Serialize(); + } + catch (Exception e) + { + testResult = (X86Serialize.X64.IsSupported || (e is not PlatformNotSupportedException)) ? Fail : Pass; + } + + return testResult; + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize_X64/Serialize.X64_r.csproj b/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize_X64/Serialize.X64_r.csproj new file mode 100644 index 0000000000000..59c9556630eed --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize_X64/Serialize.X64_r.csproj @@ -0,0 +1,13 @@ + + + Exe + true + + + Embedded + + + + + + diff --git a/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize_X64/Serialize.X64_ro.csproj b/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize_X64/Serialize.X64_ro.csproj new file mode 100644 index 0000000000000..60aa0fc71e28b --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/X86/X86Serialize_X64/Serialize.X64_ro.csproj @@ -0,0 +1,13 @@ + + + Exe + true + + + Embedded + True + + + + +