From 7c98b9c47e7a8e1a53ab6909041fb154cd389caf Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Fri, 20 Mar 2020 17:08:55 -0700 Subject: [PATCH 1/3] Revert "Revert "Unify instruction set definition (#33730)"" This reverts commit 5a71f14da2c9c2f4ef4fc1dc85f40a70bbc10dc5. --- .../superpmi-shared/methodcontext.cpp | 2 +- src/coreclr/src/inc/corinfo.h | 10 +- src/coreclr/src/inc/corinfoinstructionset.h | 276 ++++++++ src/coreclr/src/inc/corjitflags.h | 98 +-- .../src/inc/readytoruninstructionset.h | 38 ++ src/coreclr/src/jit/compiler.cpp | 286 +++----- src/coreclr/src/jit/compiler.h | 12 +- src/coreclr/src/jit/ee_il_dll.cpp | 2 +- src/coreclr/src/jit/hwintrinsic.cpp | 14 +- src/coreclr/src/jit/hwintrinsic.h | 26 +- src/coreclr/src/jit/hwintrinsicarm64.cpp | 10 +- .../src/jit/hwintrinsiccodegenxarch.cpp | 10 +- src/coreclr/src/jit/hwintrinsicxarch.cpp | 10 +- src/coreclr/src/jit/instr.h | 65 -- src/coreclr/src/jit/jitee.h | 140 +--- src/coreclr/src/jit/lsraarm64.cpp | 10 +- src/coreclr/src/jit/lsraxarch.cpp | 10 +- src/coreclr/src/jit/simdcodegenxarch.cpp | 5 - src/coreclr/src/pal/src/misc/jitsupport.cpp | 79 +-- .../Runtime/ReadyToRunInstructionSet.cs | 134 ++++ .../tools/Common/JitInterface/CorInfoImpl.cs | 57 +- .../JitInterface/CorInfoInstructionSet.cs | 317 +++++++++ .../tools/Common/JitInterface/CorInfoTypes.cs | 62 +- .../ThunkGenerator/InstructionSetDesc.txt | 81 +++ .../ThunkGenerator/InstructionSetGenerator.cs | 645 ++++++++++++++++++ .../JitInterface/ThunkGenerator/Program.cs | 47 +- .../JitInterface/ThunkGenerator/gen.bat | 6 +- .../Common/JitInterface/ThunkGenerator/gen.sh | 3 +- .../ILCompiler.ReadyToRun.csproj | 3 + .../crossgen2/jitinterface/jitwrapper.cpp | 10 +- src/coreclr/src/vm/codeman.cpp | 51 +- src/coreclr/src/zap/zapper.cpp | 30 +- 32 files changed, 1888 insertions(+), 661 deletions(-) create mode 100644 src/coreclr/src/inc/corinfoinstructionset.h create mode 100644 src/coreclr/src/inc/readytoruninstructionset.h create mode 100644 src/coreclr/src/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs create mode 100644 src/coreclr/src/tools/Common/JitInterface/CorInfoInstructionSet.cs create mode 100644 src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt create mode 100644 src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp index c4a9f4745cd13c..21c104b63db224 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp @@ -1125,7 +1125,7 @@ void MethodContext::recGetJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes, DW void MethodContext::dmpGetJitFlags(DWORD key, DD value) { CORJIT_FLAGS* jitflags = (CORJIT_FLAGS*)GetJitFlags->GetBuffer(value.A); - printf("GetJitFlags key %u sizeInBytes-%u jitFlags-%016llX", key, value.B, jitflags->GetFlagsRaw()); + printf("GetJitFlags key %u sizeInBytes-%u jitFlags-%016llX instructionSetFlags-%016llX", key, value.B, jitflags->GetFlagsRaw(), jitflags->GetInstructionSetFlagsRaw()); GetJitFlags->Unlock(); } DWORD MethodContext::repGetJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes) diff --git a/src/coreclr/src/inc/corinfo.h b/src/coreclr/src/inc/corinfo.h index 9978fac982c5cd..741b12e4f3afd6 100644 --- a/src/coreclr/src/inc/corinfo.h +++ b/src/coreclr/src/inc/corinfo.h @@ -217,11 +217,11 @@ TODO: Talk about initializing strutures before use #endif #endif -SELECTANY const GUID JITEEVersionIdentifier = { /* c231d2d7-4764-4097-a9ef-5961041540df */ - 0xc231d2d7, - 0x4764, - 0x4097, - {0xa9, 0xef, 0x59, 0x61, 0x04, 0x15, 0x40, 0xdf} +SELECTANY const GUID JITEEVersionIdentifier = { /* 54305fa1-a0d8-42e4-a6b4-b750a8143467 */ + 0x54305fa1, + 0xa0d8, + 0x42e4, + {0xa6, 0xb4, 0xb7, 0x50, 0xa8, 0x14, 0x34, 0x67} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/src/inc/corinfoinstructionset.h b/src/coreclr/src/inc/corinfoinstructionset.h new file mode 100644 index 00000000000000..d43d743134f449 --- /dev/null +++ b/src/coreclr/src/inc/corinfoinstructionset.h @@ -0,0 +1,276 @@ + +// 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. + +// DO NOT EDIT THIS FILE! IT IS AUTOGENERATED +// FROM /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +// using /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat + +#ifndef CORINFOINSTRUCTIONSET_H +#define CORINFOINSTRUCTIONSET_H + +enum CORINFO_InstructionSet +{ + InstructionSet_ILLEGAL = 0, + InstructionSet_NONE = 63, +#ifdef TARGET_ARM64 + InstructionSet_ArmBase=1, + InstructionSet_ArmBase_Arm64=2, + InstructionSet_AdvSimd=3, + InstructionSet_AdvSimd_Arm64=4, + InstructionSet_Aes=5, + InstructionSet_Crc32=6, + InstructionSet_Crc32_Arm64=7, + InstructionSet_Sha1=8, + InstructionSet_Sha256=9, + InstructionSet_Atomics=10, + InstructionSet_Vector64=11, + InstructionSet_Vector128=12, +#endif // TARGET_ARM64 +#ifdef TARGET_AMD64 + InstructionSet_SSE=1, + InstructionSet_SSE2=2, + InstructionSet_SSE3=3, + InstructionSet_SSSE3=4, + InstructionSet_SSE41=5, + InstructionSet_SSE42=6, + InstructionSet_AVX=7, + InstructionSet_AVX2=8, + InstructionSet_AES=9, + InstructionSet_BMI1=10, + InstructionSet_BMI2=11, + InstructionSet_FMA=12, + InstructionSet_LZCNT=13, + InstructionSet_PCLMULQDQ=14, + InstructionSet_POPCNT=15, + InstructionSet_Vector128=16, + InstructionSet_Vector256=17, + InstructionSet_BMI1_X64=18, + InstructionSet_BMI2_X64=19, + InstructionSet_LZCNT_X64=20, + InstructionSet_POPCNT_X64=21, + InstructionSet_SSE_X64=22, + InstructionSet_SSE2_X64=23, + InstructionSet_SSE41_X64=24, + InstructionSet_SSE42_X64=25, +#endif // TARGET_AMD64 +#ifdef TARGET_X86 + InstructionSet_SSE=1, + InstructionSet_SSE2=2, + InstructionSet_SSE3=3, + InstructionSet_SSSE3=4, + InstructionSet_SSE41=5, + InstructionSet_SSE42=6, + InstructionSet_AVX=7, + InstructionSet_AVX2=8, + InstructionSet_AES=9, + InstructionSet_BMI1=10, + InstructionSet_BMI2=11, + InstructionSet_FMA=12, + InstructionSet_LZCNT=13, + InstructionSet_PCLMULQDQ=14, + InstructionSet_POPCNT=15, + InstructionSet_Vector128=16, + InstructionSet_Vector256=17, + InstructionSet_BMI1_X64=18, + InstructionSet_BMI2_X64=19, + InstructionSet_LZCNT_X64=20, + InstructionSet_POPCNT_X64=21, + InstructionSet_SSE_X64=22, + InstructionSet_SSE2_X64=23, + InstructionSet_SSE41_X64=24, + InstructionSet_SSE42_X64=25, +#endif // TARGET_X86 + +}; + +struct CORINFO_InstructionSetFlags +{ +private: + uint64_t _flags = 0; +public: + void AddInstructionSet(CORINFO_InstructionSet instructionSet) + { + _flags = _flags | (((uint64_t)1) << instructionSet); + } + + void RemoveInstructionSet(CORINFO_InstructionSet instructionSet) + { + _flags = _flags & ~(((uint64_t)1) << instructionSet); + } + + bool HasInstructionSet(CORINFO_InstructionSet instructionSet) const + { + return _flags & (((uint64_t)1) << instructionSet); + } + + bool Equals(CORINFO_InstructionSetFlags other) const + { + return _flags == other._flags; + } + + void Add(CORINFO_InstructionSetFlags other) + { + _flags |= other._flags; + } + + bool IsEmpty() const + { + return _flags == 0; + } + + void Reset() + { + _flags = 0; + } + + void Set64BitInstructionSetVariants() + { +#ifdef TARGET_ARM64 + if (HasInstructionSet(InstructionSet_ArmBase)) + AddInstructionSet(InstructionSet_ArmBase_Arm64); + if (HasInstructionSet(InstructionSet_AdvSimd)) + AddInstructionSet(InstructionSet_AdvSimd_Arm64); + if (HasInstructionSet(InstructionSet_Crc32)) + AddInstructionSet(InstructionSet_Crc32_Arm64); +#endif // TARGET_ARM64 +#ifdef TARGET_AMD64 + if (HasInstructionSet(InstructionSet_SSE)) + AddInstructionSet(InstructionSet_SSE_X64); + if (HasInstructionSet(InstructionSet_SSE2)) + AddInstructionSet(InstructionSet_SSE2_X64); + if (HasInstructionSet(InstructionSet_SSE41)) + AddInstructionSet(InstructionSet_SSE41_X64); + if (HasInstructionSet(InstructionSet_SSE42)) + AddInstructionSet(InstructionSet_SSE42_X64); + if (HasInstructionSet(InstructionSet_BMI1)) + AddInstructionSet(InstructionSet_BMI1_X64); + if (HasInstructionSet(InstructionSet_BMI2)) + AddInstructionSet(InstructionSet_BMI2_X64); + if (HasInstructionSet(InstructionSet_LZCNT)) + AddInstructionSet(InstructionSet_LZCNT_X64); + if (HasInstructionSet(InstructionSet_POPCNT)) + AddInstructionSet(InstructionSet_POPCNT_X64); +#endif // TARGET_AMD64 +#ifdef TARGET_X86 +#endif // TARGET_X86 + + } + + uint64_t GetFlagsRaw() + { + return _flags; + } + + void SetFromFlagsRaw(uint64_t flags) + { + _flags = flags; + } +}; + +inline CORINFO_InstructionSetFlags EnsureInstructionSetFlagsAreValid(CORINFO_InstructionSetFlags input) +{ + CORINFO_InstructionSetFlags oldflags = input; + CORINFO_InstructionSetFlags resultflags = input; + do + { + oldflags = resultflags; +#ifdef TARGET_ARM64 + if (resultflags.HasInstructionSet(InstructionSet_ArmBase) && !resultflags.HasInstructionSet(InstructionSet_ArmBase_Arm64)) + resultflags.RemoveInstructionSet(InstructionSet_ArmBase); + if (resultflags.HasInstructionSet(InstructionSet_AdvSimd) && !resultflags.HasInstructionSet(InstructionSet_AdvSimd_Arm64)) + resultflags.RemoveInstructionSet(InstructionSet_AdvSimd); + if (resultflags.HasInstructionSet(InstructionSet_Crc32) && !resultflags.HasInstructionSet(InstructionSet_Crc32_Arm64)) + resultflags.RemoveInstructionSet(InstructionSet_Crc32); + if (resultflags.HasInstructionSet(InstructionSet_AdvSimd) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) + resultflags.RemoveInstructionSet(InstructionSet_AdvSimd); + if (resultflags.HasInstructionSet(InstructionSet_Aes) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) + resultflags.RemoveInstructionSet(InstructionSet_Aes); + if (resultflags.HasInstructionSet(InstructionSet_Crc32) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) + resultflags.RemoveInstructionSet(InstructionSet_Crc32); + if (resultflags.HasInstructionSet(InstructionSet_Sha1) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) + resultflags.RemoveInstructionSet(InstructionSet_Sha1); + if (resultflags.HasInstructionSet(InstructionSet_Sha256) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) + resultflags.RemoveInstructionSet(InstructionSet_Sha256); +#endif // TARGET_ARM64 +#ifdef TARGET_AMD64 + if (resultflags.HasInstructionSet(InstructionSet_SSE) && !resultflags.HasInstructionSet(InstructionSet_SSE_X64)) + resultflags.RemoveInstructionSet(InstructionSet_SSE); + if (resultflags.HasInstructionSet(InstructionSet_SSE2) && !resultflags.HasInstructionSet(InstructionSet_SSE2_X64)) + resultflags.RemoveInstructionSet(InstructionSet_SSE2); + if (resultflags.HasInstructionSet(InstructionSet_SSE41) && !resultflags.HasInstructionSet(InstructionSet_SSE41_X64)) + resultflags.RemoveInstructionSet(InstructionSet_SSE41); + if (resultflags.HasInstructionSet(InstructionSet_SSE42) && !resultflags.HasInstructionSet(InstructionSet_SSE42_X64)) + resultflags.RemoveInstructionSet(InstructionSet_SSE42); + if (resultflags.HasInstructionSet(InstructionSet_BMI1) && !resultflags.HasInstructionSet(InstructionSet_BMI1_X64)) + resultflags.RemoveInstructionSet(InstructionSet_BMI1); + if (resultflags.HasInstructionSet(InstructionSet_BMI2) && !resultflags.HasInstructionSet(InstructionSet_BMI2_X64)) + resultflags.RemoveInstructionSet(InstructionSet_BMI2); + if (resultflags.HasInstructionSet(InstructionSet_LZCNT) && !resultflags.HasInstructionSet(InstructionSet_LZCNT_X64)) + resultflags.RemoveInstructionSet(InstructionSet_LZCNT); + if (resultflags.HasInstructionSet(InstructionSet_POPCNT) && !resultflags.HasInstructionSet(InstructionSet_POPCNT_X64)) + resultflags.RemoveInstructionSet(InstructionSet_POPCNT); + if (resultflags.HasInstructionSet(InstructionSet_SSE2) && !resultflags.HasInstructionSet(InstructionSet_SSE)) + resultflags.RemoveInstructionSet(InstructionSet_SSE2); + if (resultflags.HasInstructionSet(InstructionSet_SSE3) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_SSE3); + if (resultflags.HasInstructionSet(InstructionSet_SSSE3) && !resultflags.HasInstructionSet(InstructionSet_SSE3)) + resultflags.RemoveInstructionSet(InstructionSet_SSSE3); + if (resultflags.HasInstructionSet(InstructionSet_SSE41) && !resultflags.HasInstructionSet(InstructionSet_SSSE3)) + resultflags.RemoveInstructionSet(InstructionSet_SSE41); + if (resultflags.HasInstructionSet(InstructionSet_SSE42) && !resultflags.HasInstructionSet(InstructionSet_SSE41)) + resultflags.RemoveInstructionSet(InstructionSet_SSE42); + if (resultflags.HasInstructionSet(InstructionSet_AVX) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) + resultflags.RemoveInstructionSet(InstructionSet_AVX); + if (resultflags.HasInstructionSet(InstructionSet_AVX2) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_AVX2); + if (resultflags.HasInstructionSet(InstructionSet_AES) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_AES); + if (resultflags.HasInstructionSet(InstructionSet_BMI1) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_BMI1); + if (resultflags.HasInstructionSet(InstructionSet_BMI2) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_BMI2); + if (resultflags.HasInstructionSet(InstructionSet_FMA) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_FMA); + if (resultflags.HasInstructionSet(InstructionSet_PCLMULQDQ) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_PCLMULQDQ); + if (resultflags.HasInstructionSet(InstructionSet_POPCNT) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) + resultflags.RemoveInstructionSet(InstructionSet_POPCNT); +#endif // TARGET_AMD64 +#ifdef TARGET_X86 + if (resultflags.HasInstructionSet(InstructionSet_SSE2) && !resultflags.HasInstructionSet(InstructionSet_SSE)) + resultflags.RemoveInstructionSet(InstructionSet_SSE2); + if (resultflags.HasInstructionSet(InstructionSet_SSE3) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_SSE3); + if (resultflags.HasInstructionSet(InstructionSet_SSSE3) && !resultflags.HasInstructionSet(InstructionSet_SSE3)) + resultflags.RemoveInstructionSet(InstructionSet_SSSE3); + if (resultflags.HasInstructionSet(InstructionSet_SSE41) && !resultflags.HasInstructionSet(InstructionSet_SSSE3)) + resultflags.RemoveInstructionSet(InstructionSet_SSE41); + if (resultflags.HasInstructionSet(InstructionSet_SSE42) && !resultflags.HasInstructionSet(InstructionSet_SSE41)) + resultflags.RemoveInstructionSet(InstructionSet_SSE42); + if (resultflags.HasInstructionSet(InstructionSet_AVX) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) + resultflags.RemoveInstructionSet(InstructionSet_AVX); + if (resultflags.HasInstructionSet(InstructionSet_AVX2) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_AVX2); + if (resultflags.HasInstructionSet(InstructionSet_AES) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_AES); + if (resultflags.HasInstructionSet(InstructionSet_BMI1) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_BMI1); + if (resultflags.HasInstructionSet(InstructionSet_BMI2) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_BMI2); + if (resultflags.HasInstructionSet(InstructionSet_FMA) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_FMA); + if (resultflags.HasInstructionSet(InstructionSet_PCLMULQDQ) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_PCLMULQDQ); + if (resultflags.HasInstructionSet(InstructionSet_POPCNT) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) + resultflags.RemoveInstructionSet(InstructionSet_POPCNT); +#endif // TARGET_X86 + + } while (!oldflags.Equals(resultflags)); + return resultflags; +} + + + +#endif // CORINFOINSTRUCTIONSET_H diff --git a/src/coreclr/src/inc/corjitflags.h b/src/coreclr/src/inc/corjitflags.h index 18f24b52acdfbd..eac6f9277909da 100644 --- a/src/coreclr/src/inc/corjitflags.h +++ b/src/coreclr/src/inc/corjitflags.h @@ -17,6 +17,8 @@ #ifndef _COR_JIT_FLAGS_H_ #define _COR_JIT_FLAGS_H_ +#include "corinfoinstructionset.h" + class CORJIT_FLAGS { public: @@ -40,7 +42,6 @@ class CORJIT_FLAGS CORJIT_FLAG_TARGET_P4 = 9, CORJIT_FLAG_USE_FCOMI = 10, // Generated code may use fcomi(p) instruction CORJIT_FLAG_USE_CMOV = 11, // Generated code may use cmov instruction - CORJIT_FLAG_USE_SSE2 = 12, // Generated code may use SSE-2 instructions #else // !defined(TARGET_X86) @@ -54,19 +55,10 @@ class CORJIT_FLAGS CORJIT_FLAG_OSR = 13, // Generate alternate method for On Stack Replacement - #if defined(TARGET_X86) || defined(TARGET_AMD64) - - CORJIT_FLAG_USE_AVX = 14, - CORJIT_FLAG_USE_AVX2 = 15, - CORJIT_FLAG_USE_AVX_512 = 16, - - #else // !defined(TARGET_X86) && !defined(TARGET_AMD64) - CORJIT_FLAG_UNUSED7 = 14, CORJIT_FLAG_UNUSED8 = 15, CORJIT_FLAG_UNUSED9 = 16, - #endif // !defined(TARGET_X86) && !defined(TARGET_AMD64) #if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) CORJIT_FLAG_FEATURE_SIMD = 17, @@ -106,57 +98,6 @@ class CORJIT_FLAGS CORJIT_FLAG_NO_INLINING = 42, // JIT should not inline any called method into this method -#if defined(TARGET_ARM64) - - CORJIT_FLAG_HAS_ARM64_AES = 43, // ID_AA64ISAR0_EL1.AES is 1 or better - CORJIT_FLAG_HAS_ARM64_ATOMICS = 44, // ID_AA64ISAR0_EL1.Atomic is 2 or better - CORJIT_FLAG_HAS_ARM64_CRC32 = 45, // ID_AA64ISAR0_EL1.CRC32 is 1 or better - CORJIT_FLAG_HAS_ARM64_DCPOP = 46, // ID_AA64ISAR1_EL1.DPB is 1 or better - CORJIT_FLAG_HAS_ARM64_DP = 47, // ID_AA64ISAR0_EL1.DP is 1 or better - CORJIT_FLAG_HAS_ARM64_FCMA = 48, // ID_AA64ISAR1_EL1.FCMA is 1 or better - CORJIT_FLAG_HAS_ARM64_FP = 49, // ID_AA64PFR0_EL1.FP is 0 or better - CORJIT_FLAG_HAS_ARM64_FP16 = 50, // ID_AA64PFR0_EL1.FP is 1 or better - CORJIT_FLAG_HAS_ARM64_JSCVT = 51, // ID_AA64ISAR1_EL1.JSCVT is 1 or better - CORJIT_FLAG_HAS_ARM64_LRCPC = 52, // ID_AA64ISAR1_EL1.LRCPC is 1 or better - CORJIT_FLAG_HAS_ARM64_PMULL = 53, // ID_AA64ISAR0_EL1.AES is 2 or better - CORJIT_FLAG_HAS_ARM64_SHA1 = 54, // ID_AA64ISAR0_EL1.SHA1 is 1 or better - CORJIT_FLAG_HAS_ARM64_SHA256 = 55, // ID_AA64ISAR0_EL1.SHA2 is 1 or better - CORJIT_FLAG_HAS_ARM64_SHA512 = 56, // ID_AA64ISAR0_EL1.SHA2 is 2 or better - CORJIT_FLAG_HAS_ARM64_SHA3 = 57, // ID_AA64ISAR0_EL1.SHA3 is 1 or better - CORJIT_FLAG_HAS_ARM64_ADVSIMD = 58, // ID_AA64PFR0_EL1.AdvSIMD is 0 or better - CORJIT_FLAG_HAS_ARM64_ADVSIMD_V81 = 59, // ID_AA64ISAR0_EL1.RDM is 1 or better - CORJIT_FLAG_HAS_ARM64_ADVSIMD_FP16 = 60, // ID_AA64PFR0_EL1.AdvSIMD is 1 or better - CORJIT_FLAG_HAS_ARM64_SM3 = 61, // ID_AA64ISAR0_EL1.SM3 is 1 or better - CORJIT_FLAG_HAS_ARM64_SM4 = 62, // ID_AA64ISAR0_EL1.SM4 is 1 or better - CORJIT_FLAG_HAS_ARM64_SVE = 63 // ID_AA64PFR0_EL1.SVE is 1 or better - -#elif defined(TARGET_X86) || defined(TARGET_AMD64) - - CORJIT_FLAG_USE_SSE3 = 43, - CORJIT_FLAG_USE_SSSE3 = 44, - CORJIT_FLAG_USE_SSE41 = 45, - CORJIT_FLAG_USE_SSE42 = 46, - CORJIT_FLAG_USE_AES = 47, - CORJIT_FLAG_USE_BMI1 = 48, - CORJIT_FLAG_USE_BMI2 = 49, - CORJIT_FLAG_USE_FMA = 50, - CORJIT_FLAG_USE_LZCNT = 51, - CORJIT_FLAG_USE_PCLMULQDQ = 52, - CORJIT_FLAG_USE_POPCNT = 53, - CORJIT_FLAG_UNUSED23 = 54, - CORJIT_FLAG_UNUSED24 = 55, - CORJIT_FLAG_UNUSED25 = 56, - CORJIT_FLAG_UNUSED26 = 57, - CORJIT_FLAG_UNUSED27 = 58, - CORJIT_FLAG_UNUSED28 = 59, - CORJIT_FLAG_UNUSED29 = 60, - CORJIT_FLAG_UNUSED30 = 61, - CORJIT_FLAG_UNUSED31 = 62, - CORJIT_FLAG_UNUSED32 = 63 - - -#else // !defined(TARGET_ARM64) &&!defined(TARGET_X86) && !defined(TARGET_AMD64) - CORJIT_FLAG_UNUSED12 = 43, CORJIT_FLAG_UNUSED13 = 44, CORJIT_FLAG_UNUSED14 = 45, @@ -178,8 +119,6 @@ class CORJIT_FLAGS CORJIT_FLAG_UNUSED30 = 61, CORJIT_FLAG_UNUSED31 = 62, CORJIT_FLAG_UNUSED32 = 63 - -#endif // !defined(TARGET_ARM64) &&!defined(TARGET_X86) && !defined(TARGET_AMD64) }; CORJIT_FLAGS() @@ -198,11 +137,28 @@ class CORJIT_FLAGS CORJIT_FLAGS(const CORJIT_FLAGS& other) { corJitFlags = other.corJitFlags; + instructionSetFlags = other.instructionSetFlags; } void Reset() { corJitFlags = 0; + instructionSetFlags.Reset(); + } + + void Set(CORINFO_InstructionSet instructionSet) + { + instructionSetFlags.AddInstructionSet(instructionSet); + } + + void Clear(CORINFO_InstructionSet instructionSet) + { + instructionSetFlags.RemoveInstructionSet(instructionSet); + } + + void Set64BitInstructionSetVariants() + { + instructionSetFlags.Set64BitInstructionSetVariants(); } void Set(CorJitFlag flag) @@ -223,16 +179,17 @@ class CORJIT_FLAGS void Add(const CORJIT_FLAGS& other) { corJitFlags |= other.corJitFlags; + instructionSetFlags.Add(other.instructionSetFlags); } - void Remove(const CORJIT_FLAGS& other) + bool IsEmpty() const { - corJitFlags &= ~other.corJitFlags; + return corJitFlags == 0 && instructionSetFlags.IsEmpty(); } - bool IsEmpty() const + void EnsureValidInstructionSetSupport() { - return corJitFlags == 0; + instructionSetFlags = EnsureInstructionSetFlagsAreValid(instructionSetFlags); } // DO NOT USE THIS FUNCTION! (except in very restricted special cases) @@ -241,9 +198,16 @@ class CORJIT_FLAGS return corJitFlags; } + // DO NOT USE THIS FUNCTION! (except in very restricted special cases) + unsigned __int64 GetInstructionSetFlagsRaw() + { + return instructionSetFlags.GetFlagsRaw(); + } + private: unsigned __int64 corJitFlags; + CORINFO_InstructionSetFlags instructionSetFlags; }; diff --git a/src/coreclr/src/inc/readytoruninstructionset.h b/src/coreclr/src/inc/readytoruninstructionset.h new file mode 100644 index 00000000000000..6e6f2549f90440 --- /dev/null +++ b/src/coreclr/src/inc/readytoruninstructionset.h @@ -0,0 +1,38 @@ + +// 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. + +// DO NOT EDIT THIS FILE! IT IS AUTOGENERATED +// FROM /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +// using /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat + +#ifndef READYTORUNINSTRUCTIONSET_H +#define READYTORUNINSTRUCTIONSET_H +enum ReadyToRunInstructionSet +{ + READYTORUN_INSTRUCTION_Sse=1, + READYTORUN_INSTRUCTION_Sse2=2, + READYTORUN_INSTRUCTION_Sse3=3, + READYTORUN_INSTRUCTION_Ssse3=4, + READYTORUN_INSTRUCTION_Sse41=5, + READYTORUN_INSTRUCTION_Sse42=6, + READYTORUN_INSTRUCTION_Avx=7, + READYTORUN_INSTRUCTION_Avx2=8, + READYTORUN_INSTRUCTION_Aes=9, + READYTORUN_INSTRUCTION_Bmi1=10, + READYTORUN_INSTRUCTION_Bmi2=11, + READYTORUN_INSTRUCTION_Fma=12, + READYTORUN_INSTRUCTION_Lzcnt=13, + READYTORUN_INSTRUCTION_Pclmulqdq=14, + READYTORUN_INSTRUCTION_Popcnt=15, + READYTORUN_INSTRUCTION_ArmBase=16, + READYTORUN_INSTRUCTION_AdvSimd=17, + READYTORUN_INSTRUCTION_Crc32=18, + READYTORUN_INSTRUCTION_Sha1=19, + READYTORUN_INSTRUCTION_Sha256=20, + READYTORUN_INSTRUCTION_Atomics=21, + +}; + +#endif // READYTORUNINSTRUCTIONSET_H diff --git a/src/coreclr/src/jit/compiler.cpp b/src/coreclr/src/jit/compiler.cpp index 6febed12de9fd8..0d4fc4a704dc20 100644 --- a/src/coreclr/src/jit/compiler.cpp +++ b/src/coreclr/src/jit/compiler.cpp @@ -2193,250 +2193,179 @@ void Compiler::compSetProcessor() #endif // TARGET_X86 -// Instruction set flags for Intel hardware intrinsics + CORINFO_InstructionSetFlags instructionSetFlags = jitFlags.GetInstructionSetFlags(); + #ifdef TARGET_XARCH + // Instruction set flags for Intel hardware intrinsics opts.compSupportsISA = 0; if (JitConfig.EnableHWIntrinsic()) { // Dummy ISAs for simplifying the JIT code - opts.setSupportedISA(InstructionSet_Vector128); - opts.setSupportedISA(InstructionSet_Vector256); + instructionSetFlags.AddInstructionSet(InstructionSet_Vector128); + instructionSetFlags.AddInstructionSet(InstructionSet_Vector256); } - if (JitConfig.EnableSSE()) + if (!JitConfig.EnableSSE()) { - opts.setSupportedISA(InstructionSet_SSE); + instructionSetFlags.RemoveInstructionSet(InstructionSet_SSE); #ifdef TARGET_AMD64 - opts.setSupportedISA(InstructionSet_SSE_X64); -#endif // TARGET_AMD64 - - if (JitConfig.EnableSSE2()) - { - opts.setSupportedISA(InstructionSet_SSE2); -#ifdef TARGET_AMD64 - opts.setSupportedISA(InstructionSet_SSE2_X64); -#endif // TARGET_AMD64 - - if (jitFlags.IsSet(JitFlags::JIT_FLAG_USE_AES) && JitConfig.EnableAES()) - { - opts.setSupportedISA(InstructionSet_AES); - } - - if (jitFlags.IsSet(JitFlags::JIT_FLAG_USE_PCLMULQDQ) && JitConfig.EnablePCLMULQDQ()) - { - opts.setSupportedISA(InstructionSet_PCLMULQDQ); - } - - // We need to additionaly check that COMPlus_EnableSSE3_4 is set, as that - // is a prexisting config flag that controls the SSE3+ ISAs - if (jitFlags.IsSet(JitFlags::JIT_FLAG_USE_SSE3) && JitConfig.EnableSSE3() && JitConfig.EnableSSE3_4()) - { - opts.setSupportedISA(InstructionSet_SSE3); - - if (jitFlags.IsSet(JitFlags::JIT_FLAG_USE_SSSE3) && JitConfig.EnableSSSE3()) - { - opts.setSupportedISA(InstructionSet_SSSE3); - - if (jitFlags.IsSet(JitFlags::JIT_FLAG_USE_SSE41) && JitConfig.EnableSSE41()) - { - opts.setSupportedISA(InstructionSet_SSE41); -#ifdef TARGET_AMD64 - opts.setSupportedISA(InstructionSet_SSE41_X64); -#endif // TARGET_AMD64 - - if (jitFlags.IsSet(JitFlags::JIT_FLAG_USE_SSE42) && JitConfig.EnableSSE42()) - { - opts.setSupportedISA(InstructionSet_SSE42); -#ifdef TARGET_AMD64 - opts.setSupportedISA(InstructionSet_SSE42_X64); -#endif // TARGET_AMD64 - - if (jitFlags.IsSet(JitFlags::JIT_FLAG_USE_POPCNT) && JitConfig.EnablePOPCNT()) - { - opts.setSupportedISA(InstructionSet_POPCNT); -#ifdef TARGET_AMD64 - opts.setSupportedISA(InstructionSet_POPCNT_X64); -#endif // TARGET_AMD64 - } - - if (jitFlags.IsSet(JitFlags::JIT_FLAG_USE_AVX) && JitConfig.EnableAVX()) - { - opts.setSupportedISA(InstructionSet_AVX); - - if (jitFlags.IsSet(JitFlags::JIT_FLAG_USE_FMA) && JitConfig.EnableFMA()) - { - opts.setSupportedISA(InstructionSet_FMA); - } - - if (jitFlags.IsSet(JitFlags::JIT_FLAG_USE_AVX2) && JitConfig.EnableAVX2()) - { - opts.setSupportedISA(InstructionSet_AVX2); - } - } - } - } - } - } - } - } - - if (jitFlags.IsSet(JitFlags::JIT_FLAG_USE_LZCNT) && JitConfig.EnableLZCNT()) - { - opts.setSupportedISA(InstructionSet_LZCNT); -#ifdef TARGET_AMD64 - opts.setSupportedISA(InstructionSet_LZCNT_X64); -#endif // TARGET_AMD64 - } - - // We currently need to also check that AVX is supported as that controls the support for the VEX encoding - // in the emitter. - if (jitFlags.IsSet(JitFlags::JIT_FLAG_USE_BMI1) && JitConfig.EnableBMI1() && compSupports(InstructionSet_AVX)) - { - opts.setSupportedISA(InstructionSet_BMI1); -#ifdef TARGET_AMD64 - opts.setSupportedISA(InstructionSet_BMI1_X64); -#endif // TARGET_AMD64 + instructionSetFlags.RemoveInstructionSet(InstructionSet_SSE_X64); +#endif } - // We currently need to also check that AVX is supported as that controls the support for the VEX encoding - // in the emitter. - if (jitFlags.IsSet(JitFlags::JIT_FLAG_USE_BMI2) && JitConfig.EnableBMI2() && compSupports(InstructionSet_AVX)) + if (!JitConfig.EnableSSE2()) { - opts.setSupportedISA(InstructionSet_BMI2); + instructionSetFlags.RemoveInstructionSet(InstructionSet_SSE2); #ifdef TARGET_AMD64 - opts.setSupportedISA(InstructionSet_BMI2_X64); -#endif // TARGET_AMD64 - } - - if (!compIsForInlining()) - { - if (canUseVexEncoding()) - { - codeGen->GetEmitter()->SetUseVEXEncoding(true); - // Assume each JITted method does not contain AVX instruction at first - codeGen->GetEmitter()->SetContainsAVX(false); - codeGen->GetEmitter()->SetContains256bitAVX(false); - } + instructionSetFlags.RemoveInstructionSet(InstructionSet_SSE2_X64); +#endif } -#endif // TARGET_XARCH -#if defined(TARGET_ARM64) - if (JitConfig.EnableHWIntrinsic()) + if (!JitConfig.EnableAES()) { - // Dummy ISAs for simplifying the JIT code - opts.setSupportedISA(InstructionSet_ArmBase); - opts.setSupportedISA(InstructionSet_ArmBase_Arm64); - opts.setSupportedISA(InstructionSet_Vector64); - opts.setSupportedISA(InstructionSet_Vector128); + instructionSetFlags.RemoveInstructionSet(InstructionSet_AES); } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_AES) && JitConfig.EnableArm64Aes()) + if (!JitConfig.EnablePCLMULQDQ()) { - opts.setSupportedISA(InstructionSet_Aes); + instructionSetFlags.RemoveInstructionSet(InstructionSet_PCLMULQDQ); } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_ATOMICS) && JitConfig.EnableArm64Atomics()) + // We need to additionaly check that COMPlus_EnableSSE3_4 is set, as that + // is a prexisting config flag that controls the SSE3+ ISAs + if (!JitConfig.EnableSSE3() || !JitConfig.EnableSSE3_4()) { - opts.setSupportedISA(InstructionSet_Atomics); + instructionSetFlags.RemoveInstructionSet(InstructionSet_SSE3); } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_CRC32) && JitConfig.EnableArm64Crc32()) + if (!JitConfig.EnableSSSE3()) { - opts.setSupportedISA(InstructionSet_Crc32); + instructionSetFlags.RemoveInstructionSet(InstructionSet_SSSE3); } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_DCPOP) && JitConfig.EnableArm64Dcpop()) + if (!JitConfig.EnableSSE41()) { - opts.setSupportedISA(InstructionSet_Dcpop); + instructionSetFlags.RemoveInstructionSet(InstructionSet_SSE41); +#ifdef TARGET_AMD64 + instructionSetFlags.RemoveInstructionSet(InstructionSet_SSE41_X64); +#endif } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_DP) && JitConfig.EnableArm64Dp()) + if (!JitConfig.EnableSSE42()) { - opts.setSupportedISA(InstructionSet_Dp); + instructionSetFlags.RemoveInstructionSet(InstructionSet_SSE42); +#ifdef TARGET_AMD64 + instructionSetFlags.RemoveInstructionSet(InstructionSet_SSE42_X64); +#endif } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_FCMA) && JitConfig.EnableArm64Fcma()) + if (!JitConfig.EnablePOPCNT()) { - opts.setSupportedISA(InstructionSet_Fcma); + instructionSetFlags.RemoveInstructionSet(InstructionSet_POPCNT); +#ifdef TARGET_AMD64 + instructionSetFlags.RemoveInstructionSet(InstructionSet_POPCNT_X64); +#endif } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_FP) && JitConfig.EnableArm64Fp()) + if (!JitConfig.EnableAVX()) { - opts.setSupportedISA(InstructionSet_Fp); + instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX); } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_FP16) && JitConfig.EnableArm64Fp16()) + if (!JitConfig.EnableFMA()) { - opts.setSupportedISA(InstructionSet_Fp16); + instructionSetFlags.RemoveInstructionSet(InstructionSet_FMA); } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_JSCVT) && JitConfig.EnableArm64Jscvt()) + if (!JitConfig.EnableAVX2()) { - opts.setSupportedISA(InstructionSet_Jscvt); + instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX2); } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_LRCPC) && JitConfig.EnableArm64Lrcpc()) + if (!JitConfig.EnableLZCNT()) { - opts.setSupportedISA(InstructionSet_Lrcpc); + instructionSetFlags.RemoveInstructionSet(InstructionSet_LZCNT); +#ifdef TARGET_AMD64 + instructionSetFlags.RemoveInstructionSet(InstructionSet_LZCNT_X64); +#endif // TARGET_AMD64 } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_PMULL) && JitConfig.EnableArm64Pmull()) + if (!JitConfig.EnableBMI1()) { - opts.setSupportedISA(InstructionSet_Pmull); + instructionSetFlags.RemoveInstructionSet(InstructionSet_BMI1); +#ifdef TARGET_AMD64 + instructionSetFlags.RemoveInstructionSet(InstructionSet_BMI1_X64); +#endif // TARGET_AMD64 } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_SHA1) && JitConfig.EnableArm64Sha1()) + if (!JitConfig.EnableBMI2()) { - opts.setSupportedISA(InstructionSet_Sha1); + instructionSetFlags.RemoveInstructionSet(InstructionSet_BMI2); +#ifdef TARGET_AMD64 + instructionSetFlags.RemoveInstructionSet(InstructionSet_BMI2_X64); +#endif // TARGET_AMD64 } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_SHA256) && JitConfig.EnableArm64Sha256()) +#endif // TARGET_XARCH +#if defined(TARGET_ARM64) + if (JitConfig.EnableHWIntrinsic()) { - opts.setSupportedISA(InstructionSet_Sha256); + // Dummy ISAs for simplifying the JIT code + instructionSetFlags.AddInstructionSet(InstructionSet_ArmBase); + instructionSetFlags.AddInstructionSet(InstructionSet_ArmBase_Arm64); + instructionSetFlags.AddInstructionSet(InstructionSet_Vector64); + instructionSetFlags.AddInstructionSet(InstructionSet_Vector128); } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_SHA512) && JitConfig.EnableArm64Sha512()) + if (!JitConfig.EnableArm64Aes()) { - opts.setSupportedISA(InstructionSet_Sha512); + instructionSetFlags.RemoveInstructionSet(InstructionSet_Aes); } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_SHA3) && JitConfig.EnableArm64Sha3()) + if (!JitConfig.EnableArm64Atomics()) { - opts.setSupportedISA(InstructionSet_Sha3); + instructionSetFlags.RemoveInstructionSet(InstructionSet_Atomics); } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_ADVSIMD) && JitConfig.EnableArm64AdvSimd()) + if (!JitConfig.EnableArm64Crc32()) { - opts.setSupportedISA(InstructionSet_AdvSimd); - opts.setSupportedISA(InstructionSet_AdvSimd_Arm64); + instructionSetFlags.RemoveInstructionSet(InstructionSet_Crc32); + instructionSetFlags.RemoveInstructionSet(InstructionSet_Crc32_Arm64); } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_ADVSIMD_V81) && JitConfig.EnableArm64AdvSimd_v81()) + if (!JitConfig.EnableArm64Sha1()) { - opts.setSupportedISA(InstructionSet_AdvSimd_v81); + instructionSetFlags.RemoveInstructionSet(InstructionSet_Sha1); } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_ADVSIMD_FP16) && JitConfig.EnableArm64AdvSimd_Fp16()) + if (!JitConfig.EnableArm64Sha256()) { - opts.setSupportedISA(InstructionSet_AdvSimd_Fp16); + instructionSetFlags.RemoveInstructionSet(InstructionSet_Sha256); } - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_SM3) && JitConfig.EnableArm64Sm3()) + if (!JitConfig.EnableArm64AdvSimd()) { - opts.setSupportedISA(InstructionSet_Sm3); + instructionSetFlags.RemoveInstructionSet(InstructionSet_AdvSimd); + instructionSetFlags.RemoveInstructionSet(InstructionSet_AdvSimd_Arm64); } +#endif - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_SM4) && JitConfig.EnableArm64Sm4()) - { - opts.setSupportedISA(InstructionSet_Sm4); - } + instructionSetFlags = EnsureInstructionSetFlagsAreValid(instructionSetFlags); + opts.setSupportedISAs(jitFlags.GetInstructionSetFlags()); - if (jitFlags.IsSet(JitFlags::JIT_FLAG_HAS_ARM64_SVE) && JitConfig.EnableArm64Sve()) +#ifdef TARGET_XARCH + if (!compIsForInlining()) { - opts.setSupportedISA(InstructionSet_Sve); + if (canUseVexEncoding()) + { + codeGen->GetEmitter()->SetUseVEXEncoding(true); + // Assume each JITted method does not contain AVX instruction at first + codeGen->GetEmitter()->SetContainsAVX(false); + codeGen->GetEmitter()->SetContains256bitAVX(false); + } } -#endif +#endif // TARGET_XARCH } #ifdef PROFILING_SUPPORTED @@ -5354,28 +5283,11 @@ int Compiler::compCompile(CORINFO_METHOD_HANDLE methodHnd, // target default. Currently this is disabling all ARM64 architecture features except FP and SIMD, but this // should be altered to possibly enable all of them, when they are known to all work. - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_AES); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_ATOMICS); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_CRC32); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_DCPOP); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_DP); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_FCMA); - compileFlags->Set(JitFlags::JIT_FLAG_HAS_ARM64_FP); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_FP16); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_JSCVT); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_LRCPC); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_PMULL); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_SHA1); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_SHA256); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_SHA512); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_SHA3); - compileFlags->Set(JitFlags::JIT_FLAG_HAS_ARM64_ADVSIMD); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_ADVSIMD_V81); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_ADVSIMD_FP16); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_SM3); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_SM4); - compileFlags->Clear(JitFlags::JIT_FLAG_HAS_ARM64_SVE); - + CORINFO_InstructionSetFlags defaultArm64Flags; + defaultArm64Flags.AddInstructionSet(InstructionSet_ArmBase); + defaultArm64Flags.AddInstructionSet(InstructionSet_AdvSimd); + defaultArm64Flags.Set64BitInstructionSetVariants(); + compileFlags->SetInstructionSetFlags(defaultArm64Flags); #endif // defined(TARGET_ARM64) } diff --git a/src/coreclr/src/jit/compiler.h b/src/coreclr/src/jit/compiler.h index 109c9b43839d50..64b719f160f988 100644 --- a/src/coreclr/src/jit/compiler.h +++ b/src/coreclr/src/jit/compiler.h @@ -3674,7 +3674,7 @@ class Compiler bool mustExpand); protected: - bool compSupportsHWIntrinsic(InstructionSet isa); + bool compSupportsHWIntrinsic(CORINFO_InstructionSet isa); GenTree* impSpecialIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, @@ -8272,7 +8272,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX return false; } - bool compSupports(InstructionSet isa) const + bool compSupports(CORINFO_InstructionSet isa) const { #if defined(TARGET_XARCH) || defined(TARGET_ARM64) return (opts.compSupportsISA & (1ULL << isa)) != 0; @@ -8381,11 +8381,13 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #if defined(TARGET_XARCH) || defined(TARGET_ARM64) uint64_t compSupportsISA; - void setSupportedISA(InstructionSet isa) +#endif + void setSupportedISAs(CORINFO_InstructionSetFlags isas) { - compSupportsISA |= 1ULL << isa; - } +#if defined(TARGET_XARCH) || defined(TARGET_ARM64) + compSupportsISA = isas.GetFlagsRaw(); #endif + } unsigned compFlags; // method attributes unsigned instrCount; diff --git a/src/coreclr/src/jit/ee_il_dll.cpp b/src/coreclr/src/jit/ee_il_dll.cpp index 4ac4c24dfde058..78d3d8e59274aa 100644 --- a/src/coreclr/src/jit/ee_il_dll.cpp +++ b/src/coreclr/src/jit/ee_il_dll.cpp @@ -340,7 +340,7 @@ unsigned CILJit::getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags) #ifdef FEATURE_SIMD #if defined(TARGET_XARCH) if (!jitFlags.IsSet(JitFlags::JIT_FLAG_PREJIT) && jitFlags.IsSet(JitFlags::JIT_FLAG_FEATURE_SIMD) && - jitFlags.IsSet(JitFlags::JIT_FLAG_USE_AVX2)) + jitFlags.GetInstructionSetFlags().HasInstructionSet(InstructionSet_AVX2)) { // Since the ISAs can be disabled individually and since they are hierarchical in nature (that is // disabling SSE also disables SSE2 through AVX2), we need to check each ISA in the hierarchy to diff --git a/src/coreclr/src/jit/hwintrinsic.cpp b/src/coreclr/src/jit/hwintrinsic.cpp index 4b8848bbf458cf..4af653b766e6be 100644 --- a/src/coreclr/src/jit/hwintrinsic.cpp +++ b/src/coreclr/src/jit/hwintrinsic.cpp @@ -302,7 +302,7 @@ NamedIntrinsic HWIntrinsicInfo::lookupId(Compiler* comp, const char* enclosingClassName) { // TODO-Throughput: replace sequential search by binary search - InstructionSet isa = lookupIsa(className, enclosingClassName); + CORINFO_InstructionSet isa = lookupIsa(className, enclosingClassName); if (isa == InstructionSet_ILLEGAL) { @@ -584,7 +584,7 @@ GenTree* Compiler::addRangeCheckIfNeeded(NamedIntrinsic intrinsic, GenTree* immO // // Return Value: // true iff the given instruction set is supported in the current compilation. -bool Compiler::compSupportsHWIntrinsic(InstructionSet isa) +bool Compiler::compSupportsHWIntrinsic(CORINFO_InstructionSet isa) { return JitConfig.EnableHWIntrinsic() && (featureSIMD || HWIntrinsicInfo::isScalarIsa(isa)) && ( @@ -629,11 +629,11 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, CORINFO_SIG_INFO* sig, bool mustExpand) { - InstructionSet isa = HWIntrinsicInfo::lookupIsa(intrinsic); - HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsic); - int numArgs = sig->numArgs; - var_types retType = JITtype2varType(sig->retType); - var_types baseType = TYP_UNKNOWN; + CORINFO_InstructionSet isa = HWIntrinsicInfo::lookupIsa(intrinsic); + HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsic); + int numArgs = sig->numArgs; + var_types retType = JITtype2varType(sig->retType); + var_types baseType = TYP_UNKNOWN; if ((retType == TYP_STRUCT) && featureSIMD) { diff --git a/src/coreclr/src/jit/hwintrinsic.h b/src/coreclr/src/jit/hwintrinsic.h index 2931c51813e1ed..b80dce7f1c0b00 100644 --- a/src/coreclr/src/jit/hwintrinsic.h +++ b/src/coreclr/src/jit/hwintrinsic.h @@ -113,15 +113,15 @@ enum HWIntrinsicFlag : unsigned int struct HWIntrinsicInfo { - NamedIntrinsic id; - const char* name; - InstructionSet isa; - int ival; - unsigned simdSize; - int numArgs; - instruction ins[10]; - HWIntrinsicCategory category; - HWIntrinsicFlag flags; + NamedIntrinsic id; + const char* name; + CORINFO_InstructionSet isa; + int ival; + unsigned simdSize; + int numArgs; + instruction ins[10]; + HWIntrinsicCategory category; + HWIntrinsicFlag flags; static const HWIntrinsicInfo& lookup(NamedIntrinsic id); @@ -129,7 +129,7 @@ struct HWIntrinsicInfo const char* className, const char* methodName, const char* enclosingClassName); - static InstructionSet lookupIsa(const char* className, const char* enclosingClassName); + static CORINFO_InstructionSet lookupIsa(const char* className, const char* enclosingClassName); static unsigned lookupSimdSize(Compiler* comp, NamedIntrinsic id, CORINFO_SIG_INFO* sig); static int lookupNumArgs(const GenTreeHWIntrinsic* node); @@ -138,8 +138,8 @@ struct HWIntrinsicInfo static bool isImmOp(NamedIntrinsic id, const GenTree* op); static bool isInImmRange(NamedIntrinsic id, int ival); - static bool isFullyImplementedIsa(InstructionSet isa); - static bool isScalarIsa(InstructionSet isa); + static bool isFullyImplementedIsa(CORINFO_InstructionSet isa); + static bool isScalarIsa(CORINFO_InstructionSet isa); #ifdef TARGET_XARCH static bool isAVX2GatherIntrinsic(NamedIntrinsic id); @@ -157,7 +157,7 @@ struct HWIntrinsicInfo return lookup(id).name; } - static InstructionSet lookupIsa(NamedIntrinsic id) + static CORINFO_InstructionSet lookupIsa(NamedIntrinsic id) { return lookup(id).isa; } diff --git a/src/coreclr/src/jit/hwintrinsicarm64.cpp b/src/coreclr/src/jit/hwintrinsicarm64.cpp index 1f7dde990cc7d7..7f494ab96582f5 100644 --- a/src/coreclr/src/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/src/jit/hwintrinsicarm64.cpp @@ -15,7 +15,7 @@ // // Return Value: // The 64-bit only InstructionSet associated with isa -static InstructionSet Arm64VersionOfIsa(InstructionSet isa) +static CORINFO_InstructionSet Arm64VersionOfIsa(CORINFO_InstructionSet isa) { switch (isa) { @@ -38,7 +38,7 @@ static InstructionSet Arm64VersionOfIsa(InstructionSet isa) // // Return Value: // The InstructionSet associated with className -static InstructionSet lookupInstructionSet(const char* className) +static CORINFO_InstructionSet lookupInstructionSet(const char* className) { assert(className != nullptr); @@ -99,7 +99,7 @@ static InstructionSet lookupInstructionSet(const char* className) // // Return Value: // The InstructionSet associated with className and enclosingClassName -InstructionSet HWIntrinsicInfo::lookupIsa(const char* className, const char* enclosingClassName) +CORINFO_InstructionSet HWIntrinsicInfo::lookupIsa(const char* className, const char* enclosingClassName) { assert(className != nullptr); @@ -153,7 +153,7 @@ bool HWIntrinsicInfo::isInImmRange(NamedIntrinsic id, int ival) // // Return Value: // true if isa is supported; otherwise, false -bool HWIntrinsicInfo::isFullyImplementedIsa(InstructionSet isa) +bool HWIntrinsicInfo::isFullyImplementedIsa(CORINFO_InstructionSet isa) { switch (isa) { @@ -188,7 +188,7 @@ bool HWIntrinsicInfo::isFullyImplementedIsa(InstructionSet isa) // // Return Value: // true if isa is scalar; otherwise, false -bool HWIntrinsicInfo::isScalarIsa(InstructionSet isa) +bool HWIntrinsicInfo::isScalarIsa(CORINFO_InstructionSet isa) { switch (isa) { diff --git a/src/coreclr/src/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/src/jit/hwintrinsiccodegenxarch.cpp index 1ba67be0bb2d9e..cb5160e5cb9373 100644 --- a/src/coreclr/src/jit/hwintrinsiccodegenxarch.cpp +++ b/src/coreclr/src/jit/hwintrinsiccodegenxarch.cpp @@ -79,11 +79,11 @@ static bool genIsTableDrivenHWIntrinsic(NamedIntrinsic intrinsicId, HWIntrinsicC // void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) { - NamedIntrinsic intrinsicId = node->gtHWIntrinsicId; - InstructionSet isa = HWIntrinsicInfo::lookupIsa(intrinsicId); - HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId); - int ival = HWIntrinsicInfo::lookupIval(intrinsicId); - int numArgs = HWIntrinsicInfo::lookupNumArgs(node); + NamedIntrinsic intrinsicId = node->gtHWIntrinsicId; + CORINFO_InstructionSet isa = HWIntrinsicInfo::lookupIsa(intrinsicId); + HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId); + int ival = HWIntrinsicInfo::lookupIval(intrinsicId); + int numArgs = HWIntrinsicInfo::lookupNumArgs(node); assert(HWIntrinsicInfo::RequiresCodegen(intrinsicId)); diff --git a/src/coreclr/src/jit/hwintrinsicxarch.cpp b/src/coreclr/src/jit/hwintrinsicxarch.cpp index 6aa59aa2bb7f68..80b341f1c90ecb 100644 --- a/src/coreclr/src/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/src/jit/hwintrinsicxarch.cpp @@ -15,7 +15,7 @@ // // Return Value: // The 64-bit only InstructionSet associated with isa -static InstructionSet X64VersionOfIsa(InstructionSet isa) +static CORINFO_InstructionSet X64VersionOfIsa(CORINFO_InstructionSet isa) { switch (isa) { @@ -48,7 +48,7 @@ static InstructionSet X64VersionOfIsa(InstructionSet isa) // // Return Value: // The InstructionSet associated with className -static InstructionSet lookupInstructionSet(const char* className) +static CORINFO_InstructionSet lookupInstructionSet(const char* className) { assert(className != nullptr); if (className[0] == 'A') @@ -147,7 +147,7 @@ static InstructionSet lookupInstructionSet(const char* className) // // Return Value: // The InstructionSet associated with className and enclosingClassName -InstructionSet HWIntrinsicInfo::lookupIsa(const char* className, const char* enclosingClassName) +CORINFO_InstructionSet HWIntrinsicInfo::lookupIsa(const char* className, const char* enclosingClassName) { assert(className != nullptr); @@ -253,7 +253,7 @@ bool HWIntrinsicInfo::isAVX2GatherIntrinsic(NamedIntrinsic id) // // Return Value: // true if isa is supported; otherwise, false -bool HWIntrinsicInfo::isFullyImplementedIsa(InstructionSet isa) +bool HWIntrinsicInfo::isFullyImplementedIsa(CORINFO_InstructionSet isa) { switch (isa) { @@ -302,7 +302,7 @@ bool HWIntrinsicInfo::isFullyImplementedIsa(InstructionSet isa) // // Return Value: // true if isa is scalar; otherwise, false -bool HWIntrinsicInfo::isScalarIsa(InstructionSet isa) +bool HWIntrinsicInfo::isScalarIsa(CORINFO_InstructionSet isa) { switch (isa) { diff --git a/src/coreclr/src/jit/instr.h b/src/coreclr/src/jit/instr.h index 0de79a4cc1387f..26ba6eec4ac016 100644 --- a/src/coreclr/src/jit/instr.h +++ b/src/coreclr/src/jit/instr.h @@ -292,71 +292,6 @@ enum emitAttr : unsigned #define EmitSize(x) (EA_ATTR(genTypeSize(TypeGet(x)))) -enum InstructionSet -{ - InstructionSet_ILLEGAL = 0, -#ifdef TARGET_XARCH - InstructionSet_Vector128, - InstructionSet_Vector256, - // Start linear order SIMD instruction sets - // These ISAs have strictly generation to generation order. - InstructionSet_SSE, - InstructionSet_SSE2, - InstructionSet_SSE3, - InstructionSet_SSSE3, - InstructionSet_SSE41, - InstructionSet_SSE42, - InstructionSet_AVX, - InstructionSet_AVX2, - // End linear order SIMD instruction sets. - InstructionSet_AES, - InstructionSet_BMI1, - InstructionSet_BMI2, - InstructionSet_FMA, - InstructionSet_LZCNT, - InstructionSet_PCLMULQDQ, - InstructionSet_POPCNT, - InstructionSet_BMI1_X64, - InstructionSet_BMI2_X64, - InstructionSet_LZCNT_X64, - InstructionSet_POPCNT_X64, - InstructionSet_SSE_X64, - InstructionSet_SSE2_X64, - InstructionSet_SSE41_X64, - InstructionSet_SSE42_X64, -#elif defined(TARGET_ARM) - InstructionSet_NEON, -#elif defined(TARGET_ARM64) - InstructionSet_AdvSimd, // ID_AA64PFR0_EL1.AdvSIMD is 0 or better - InstructionSet_AdvSimd_Arm64, - InstructionSet_AdvSimd_Fp16, // ID_AA64PFR0_EL1.AdvSIMD is 1 or better - InstructionSet_AdvSimd_v81, // ID_AA64ISAR0_EL1.RDM is 1 or better - InstructionSet_Aes, // ID_AA64ISAR0_EL1.AES is 1 or better - InstructionSet_ArmBase, - 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 - InstructionSet_Fp, // ID_AA64PFR0_EL1.FP is 0 or better - InstructionSet_Fp16, // ID_AA64PFR0_EL1.FP is 1 or better - InstructionSet_Jscvt, // ID_AA64ISAR1_EL1.JSCVT is 1 or better - InstructionSet_Lrcpc, // ID_AA64ISAR1_EL1.LRCPC is 1 or better - InstructionSet_Pmull, // ID_AA64ISAR0_EL1.AES is 2 or better - InstructionSet_Sha1, // ID_AA64ISAR0_EL1.SHA1 is 1 or better - InstructionSet_Sha256, // ID_AA64ISAR0_EL1.SHA2 is 1 or better - InstructionSet_Sha512, // ID_AA64ISAR0_EL1.SHA2 is 2 or better - InstructionSet_Sha3, // ID_AA64ISAR0_EL1.SHA3 is 1 or better - InstructionSet_Sm3, // ID_AA64ISAR0_EL1.SM3 is 1 or better - InstructionSet_Sm4, // ID_AA64ISAR0_EL1.SM4 is 1 or better - InstructionSet_Sve, // ID_AA64PFR0_EL1.SVE is 1 or better - InstructionSet_Vector64, - InstructionSet_Vector128, -#endif - InstructionSet_NONE // No instruction set is available indicating an invalid value -}; // clang-format on /*****************************************************************************/ diff --git a/src/coreclr/src/jit/jitee.h b/src/coreclr/src/jit/jitee.h index 473bfc58ff123c..405ef9a7d74219 100644 --- a/src/coreclr/src/jit/jitee.h +++ b/src/coreclr/src/jit/jitee.h @@ -27,7 +27,6 @@ class JitFlags JIT_FLAG_TARGET_P4 = 9, JIT_FLAG_USE_FCOMI = 10, // Generated code may use fcomi(p) instruction JIT_FLAG_USE_CMOV = 11, // Generated code may use cmov instruction - JIT_FLAG_USE_SSE2 = 12, // Generated code may use SSE-2 instructions #else // !defined(TARGET_X86) @@ -41,20 +40,10 @@ class JitFlags JIT_FLAG_OSR = 13, // Generate alternate version for On Stack Replacement - #if defined(TARGET_X86) || defined(TARGET_AMD64) - - JIT_FLAG_USE_AVX = 14, - JIT_FLAG_USE_AVX2 = 15, - JIT_FLAG_USE_AVX_512 = 16, - - #else // !defined(TARGET_X86) && !defined(TARGET_AMD64) - JIT_FLAG_UNUSED7 = 14, JIT_FLAG_UNUSED8 = 15, JIT_FLAG_UNUSED9 = 16, - #endif // !defined(TARGET_X86) && !defined(TARGET_AMD64) - #if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) JIT_FLAG_FEATURE_SIMD = 17, #else @@ -93,57 +82,6 @@ class JitFlags JIT_FLAG_NO_INLINING = 42, // JIT should not inline any called method into this method -#if defined(TARGET_ARM64) - - JIT_FLAG_HAS_ARM64_AES = 43, // ID_AA64ISAR0_EL1.AES is 1 or better - JIT_FLAG_HAS_ARM64_ATOMICS = 44, // ID_AA64ISAR0_EL1.Atomic is 2 or better - JIT_FLAG_HAS_ARM64_CRC32 = 45, // ID_AA64ISAR0_EL1.CRC32 is 1 or better - JIT_FLAG_HAS_ARM64_DCPOP = 46, // ID_AA64ISAR1_EL1.DPB is 1 or better - JIT_FLAG_HAS_ARM64_DP = 47, // ID_AA64ISAR0_EL1.DP is 1 or better - JIT_FLAG_HAS_ARM64_FCMA = 48, // ID_AA64ISAR1_EL1.FCMA is 1 or better - JIT_FLAG_HAS_ARM64_FP = 49, // ID_AA64PFR0_EL1.FP is 0 or better - JIT_FLAG_HAS_ARM64_FP16 = 50, // ID_AA64PFR0_EL1.FP is 1 or better - JIT_FLAG_HAS_ARM64_JSCVT = 51, // ID_AA64ISAR1_EL1.JSCVT is 1 or better - JIT_FLAG_HAS_ARM64_LRCPC = 52, // ID_AA64ISAR1_EL1.LRCPC is 1 or better - JIT_FLAG_HAS_ARM64_PMULL = 53, // ID_AA64ISAR0_EL1.AES is 2 or better - JIT_FLAG_HAS_ARM64_SHA1 = 54, // ID_AA64ISAR0_EL1.SHA1 is 1 or better - JIT_FLAG_HAS_ARM64_SHA256 = 55, // ID_AA64ISAR0_EL1.SHA2 is 1 or better - JIT_FLAG_HAS_ARM64_SHA512 = 56, // ID_AA64ISAR0_EL1.SHA2 is 2 or better - JIT_FLAG_HAS_ARM64_SHA3 = 57, // ID_AA64ISAR0_EL1.SHA3 is 1 or better - JIT_FLAG_HAS_ARM64_ADVSIMD = 58, // ID_AA64PFR0_EL1.AdvSIMD is 0 or better - JIT_FLAG_HAS_ARM64_ADVSIMD_V81 = 59, // ID_AA64ISAR0_EL1.RDM is 1 or better - JIT_FLAG_HAS_ARM64_ADVSIMD_FP16 = 60, // ID_AA64PFR0_EL1.AdvSIMD is 1 or better - JIT_FLAG_HAS_ARM64_SM3 = 61, // ID_AA64ISAR0_EL1.SM3 is 1 or better - JIT_FLAG_HAS_ARM64_SM4 = 62, // ID_AA64ISAR0_EL1.SM4 is 1 or better - JIT_FLAG_HAS_ARM64_SVE = 63 // ID_AA64PFR0_EL1.SVE is 1 or better - -#elif defined(TARGET_X86) || defined(TARGET_AMD64) - - JIT_FLAG_USE_SSE3 = 43, - JIT_FLAG_USE_SSSE3 = 44, - JIT_FLAG_USE_SSE41 = 45, - JIT_FLAG_USE_SSE42 = 46, - JIT_FLAG_USE_AES = 47, - JIT_FLAG_USE_BMI1 = 48, - JIT_FLAG_USE_BMI2 = 49, - JIT_FLAG_USE_FMA = 50, - JIT_FLAG_USE_LZCNT = 51, - JIT_FLAG_USE_PCLMULQDQ = 52, - JIT_FLAG_USE_POPCNT = 53, - JIT_FLAG_UNUSED23 = 54, - JIT_FLAG_UNUSED24 = 55, - JIT_FLAG_UNUSED25 = 56, - JIT_FLAG_UNUSED26 = 57, - JIT_FLAG_UNUSED27 = 58, - JIT_FLAG_UNUSED28 = 59, - JIT_FLAG_UNUSED29 = 60, - JIT_FLAG_UNUSED30 = 61, - JIT_FLAG_UNUSED31 = 62, - JIT_FLAG_UNUSED32 = 63 - - -#else // !defined(TARGET_ARM64) && !defined(TARGET_X86) && !defined(TARGET_AMD64) - JIT_FLAG_UNUSED12 = 43, JIT_FLAG_UNUSED13 = 44, JIT_FLAG_UNUSED14 = 45, @@ -166,8 +104,6 @@ class JitFlags JIT_FLAG_UNUSED31 = 62, JIT_FLAG_UNUSED32 = 63 -#endif // !defined(TARGET_ARM64) && !defined(TARGET_X86) && !defined(TARGET_AMD64) - }; // clang-format on @@ -187,29 +123,29 @@ class JitFlags m_jitFlags = 0; } - void Set(JitFlag flag) + CORINFO_InstructionSetFlags GetInstructionSetFlags() const { - m_jitFlags |= 1ULL << (unsigned __int64)flag; + return m_instructionSetFlags; } - void Clear(JitFlag flag) + void SetInstructionSetFlags(CORINFO_InstructionSetFlags instructionSetFlags) { - m_jitFlags &= ~(1ULL << (unsigned __int64)flag); + m_instructionSetFlags = instructionSetFlags; } - bool IsSet(JitFlag flag) const + void Set(JitFlag flag) { - return (m_jitFlags & (1ULL << (unsigned __int64)flag)) != 0; + m_jitFlags |= 1ULL << (unsigned __int64)flag; } - void Add(const JitFlags& other) + void Clear(JitFlag flag) { - m_jitFlags |= other.m_jitFlags; + m_jitFlags &= ~(1ULL << (unsigned __int64)flag); } - void Remove(const JitFlags& other) + bool IsSet(JitFlag flag) const { - m_jitFlags &= ~other.m_jitFlags; + return (m_jitFlags & (1ULL << (unsigned __int64)flag)) != 0; } bool IsEmpty() const @@ -222,8 +158,9 @@ class JitFlags // We don't want to have to check every one, so we assume it is exactly the same values as the JitFlag // values defined in this type. m_jitFlags = flags.GetFlagsRaw(); + m_instructionSetFlags.SetFromFlagsRaw(flags.GetInstructionSetFlagsRaw()); - C_ASSERT(sizeof(m_jitFlags) == sizeof(CORJIT_FLAGS)); + C_ASSERT(sizeof(JitFlags) == sizeof(CORJIT_FLAGS)); #define FLAGS_EQUAL(a, b) C_ASSERT((unsigned)(a) == (unsigned)(b)) @@ -242,15 +179,6 @@ class JitFlags FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_TARGET_P4, JIT_FLAG_TARGET_P4); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_FCOMI, JIT_FLAG_USE_FCOMI); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_CMOV, JIT_FLAG_USE_CMOV); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE2, JIT_FLAG_USE_SSE2); - -#endif - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_AVX, JIT_FLAG_USE_AVX); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_AVX2, JIT_FLAG_USE_AVX2); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_AVX_512, JIT_FLAG_USE_AVX_512); #endif @@ -290,50 +218,10 @@ class JitFlags #endif // TARGET_ARM FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_NO_INLINING, JIT_FLAG_NO_INLINING); - -#if defined(TARGET_ARM64) - - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_AES, JIT_FLAG_HAS_ARM64_AES); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ATOMICS, JIT_FLAG_HAS_ARM64_ATOMICS); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_CRC32, JIT_FLAG_HAS_ARM64_CRC32); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_DCPOP, JIT_FLAG_HAS_ARM64_DCPOP); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_DP, JIT_FLAG_HAS_ARM64_DP); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FCMA, JIT_FLAG_HAS_ARM64_FCMA); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP, JIT_FLAG_HAS_ARM64_FP); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP16, JIT_FLAG_HAS_ARM64_FP16); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_JSCVT, JIT_FLAG_HAS_ARM64_JSCVT); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_LRCPC, JIT_FLAG_HAS_ARM64_LRCPC); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_PMULL, JIT_FLAG_HAS_ARM64_PMULL); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA1, JIT_FLAG_HAS_ARM64_SHA1); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA256, JIT_FLAG_HAS_ARM64_SHA256); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA512, JIT_FLAG_HAS_ARM64_SHA512); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA3, JIT_FLAG_HAS_ARM64_SHA3); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ADVSIMD, JIT_FLAG_HAS_ARM64_ADVSIMD); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ADVSIMD_V81, JIT_FLAG_HAS_ARM64_ADVSIMD_V81); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ADVSIMD_FP16, JIT_FLAG_HAS_ARM64_ADVSIMD_FP16); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SM3, JIT_FLAG_HAS_ARM64_SM3); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SM4, JIT_FLAG_HAS_ARM64_SM4); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SVE, JIT_FLAG_HAS_ARM64_SVE); - -#elif defined(TARGET_X86) || defined(TARGET_AMD64) - - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE3, JIT_FLAG_USE_SSE3); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_SSSE3, JIT_FLAG_USE_SSSE3); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE41, JIT_FLAG_USE_SSE41); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE42, JIT_FLAG_USE_SSE42); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_AES, JIT_FLAG_USE_AES); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_BMI1, JIT_FLAG_USE_BMI1); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_BMI2, JIT_FLAG_USE_BMI2); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_FMA, JIT_FLAG_USE_FMA); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_LZCNT, JIT_FLAG_USE_LZCNT); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_PCLMULQDQ, JIT_FLAG_USE_PCLMULQDQ); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_POPCNT, JIT_FLAG_USE_POPCNT); - -#endif // TARGET_X86 || TARGET_AMD64 - #undef FLAGS_EQUAL } private: - unsigned __int64 m_jitFlags; + unsigned __int64 m_jitFlags; + CORINFO_InstructionSetFlags m_instructionSetFlags; }; diff --git a/src/coreclr/src/jit/lsraarm64.cpp b/src/coreclr/src/jit/lsraarm64.cpp index 6a695a1185a0a0..b9de46de1910b8 100644 --- a/src/coreclr/src/jit/lsraarm64.cpp +++ b/src/coreclr/src/jit/lsraarm64.cpp @@ -994,11 +994,11 @@ int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) // int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) { - NamedIntrinsic intrinsicId = intrinsicTree->gtHWIntrinsicId; - var_types baseType = intrinsicTree->gtSIMDBaseType; - InstructionSet isa = HWIntrinsicInfo::lookupIsa(intrinsicId); - HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId); - int numArgs = HWIntrinsicInfo::lookupNumArgs(intrinsicTree); + NamedIntrinsic intrinsicId = intrinsicTree->gtHWIntrinsicId; + var_types baseType = intrinsicTree->gtSIMDBaseType; + CORINFO_InstructionSet isa = HWIntrinsicInfo::lookupIsa(intrinsicId); + HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId); + int numArgs = HWIntrinsicInfo::lookupNumArgs(intrinsicTree); GenTree* op1 = intrinsicTree->gtGetOp1(); GenTree* op2 = intrinsicTree->gtGetOp2(); diff --git a/src/coreclr/src/jit/lsraxarch.cpp b/src/coreclr/src/jit/lsraxarch.cpp index 19c914e614d91b..2578cd7fbdc925 100644 --- a/src/coreclr/src/jit/lsraxarch.cpp +++ b/src/coreclr/src/jit/lsraxarch.cpp @@ -2286,11 +2286,11 @@ int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) // int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) { - NamedIntrinsic intrinsicId = intrinsicTree->gtHWIntrinsicId; - var_types baseType = intrinsicTree->gtSIMDBaseType; - InstructionSet isa = HWIntrinsicInfo::lookupIsa(intrinsicId); - HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId); - int numArgs = HWIntrinsicInfo::lookupNumArgs(intrinsicTree); + NamedIntrinsic intrinsicId = intrinsicTree->gtHWIntrinsicId; + var_types baseType = intrinsicTree->gtSIMDBaseType; + CORINFO_InstructionSet isa = HWIntrinsicInfo::lookupIsa(intrinsicId); + HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId); + int numArgs = HWIntrinsicInfo::lookupNumArgs(intrinsicTree); // Set the AVX Flags if this instruction may use VEX encoding for SIMD operations. // Note that this may be true even if the ISA is not AVX (e.g. for platform-agnostic intrinsics diff --git a/src/coreclr/src/jit/simdcodegenxarch.cpp b/src/coreclr/src/jit/simdcodegenxarch.cpp index d49fa6008451d8..8ca69e35be37ac 100644 --- a/src/coreclr/src/jit/simdcodegenxarch.cpp +++ b/src/coreclr/src/jit/simdcodegenxarch.cpp @@ -73,11 +73,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type { // AVX supports broadcast instructions to populate YMM reg with a single float/double value from memory. // AVX2 supports broadcast instructions to populate YMM reg with a single value from memory or mm reg. - // If we decide to use AVX2 only, we can remove this assert. - if (!compiler->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_USE_AVX2)) - { - assert(baseType == TYP_FLOAT || baseType == TYP_DOUBLE); - } switch (baseType) { case TYP_FLOAT: diff --git a/src/coreclr/src/pal/src/misc/jitsupport.cpp b/src/coreclr/src/pal/src/misc/jitsupport.cpp index 0da36ab8903a68..70123f8d18faaf 100644 --- a/src/coreclr/src/pal/src/misc/jitsupport.cpp +++ b/src/coreclr/src/pal/src/misc/jitsupport.cpp @@ -21,11 +21,11 @@ PAL_GetJitCpuCapabilityFlags(CORJIT_FLAGS *flags) { _ASSERTE(flags); + CORJIT_FLAGS &CPUCompileFlags = *flags; #if defined(HOST_ARM64) #if HAVE_AUXV_HWCAP_H unsigned long hwCap = getauxval(AT_HWCAP); - CORJIT_FLAGS &CPUCompileFlags = *flags; // HWCAP_* flags are introduced by ARM into the Linux kernel as new extensions are published. // For a given kernel, some of these flags may not be present yet. // Use ifdef for each to allow for compilation with any vintage kernel. @@ -34,95 +34,96 @@ PAL_GetJitCpuCapabilityFlags(CORJIT_FLAGS *flags) // available, using the latest kernel for release should be sufficient. #ifdef HWCAP_AES if (hwCap & HWCAP_AES) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_AES); + CPUCompileFlags.Set(InstructionSet_Aes); #endif #ifdef HWCAP_ATOMICS if (hwCap & HWCAP_ATOMICS) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ATOMICS); + CPUCompileFlags.Set(InstructionSet_Atomics); #endif #ifdef HWCAP_CRC32 if (hwCap & HWCAP_CRC32) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_CRC32); + CPUCompileFlags.Set(InstructionSet_Crc32); #endif #ifdef HWCAP_DCPOP - if (hwCap & HWCAP_DCPOP) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_DCPOP); +// if (hwCap & HWCAP_DCPOP) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_DCPOP); #endif #ifdef HWCAP_ASIMDDP - if (hwCap & HWCAP_ASIMDDP) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_DP); +// if (hwCap & HWCAP_ASIMDDP) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_DP); #endif #ifdef HWCAP_FCMA - if (hwCap & HWCAP_FCMA) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FCMA); +// if (hwCap & HWCAP_FCMA) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FCMA); #endif #ifdef HWCAP_FP - if (hwCap & HWCAP_FP) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP); +// if (hwCap & HWCAP_FP) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP); #endif #ifdef HWCAP_FPHP - if (hwCap & HWCAP_FPHP) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP16); +// if (hwCap & HWCAP_FPHP) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP16); #endif #ifdef HWCAP_JSCVT - if (hwCap & HWCAP_JSCVT) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_JSCVT); +// if (hwCap & HWCAP_JSCVT) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_JSCVT); #endif #ifdef HWCAP_LRCPC - if (hwCap & HWCAP_LRCPC) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_LRCPC); +// if (hwCap & HWCAP_LRCPC) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_LRCPC); #endif #ifdef HWCAP_PMULL - if (hwCap & HWCAP_PMULL) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_PMULL); +// if (hwCap & HWCAP_PMULL) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_PMULL); #endif #ifdef HWCAP_SHA1 if (hwCap & HWCAP_SHA1) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA1); + CPUCompileFlags.Set(InstructionSet_Sha1); #endif #ifdef HWCAP_SHA2 if (hwCap & HWCAP_SHA2) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA256); + CPUCompileFlags.Set(InstructionSet_Sha256); #endif #ifdef HWCAP_SHA512 - if (hwCap & HWCAP_SHA512) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA512); +// if (hwCap & HWCAP_SHA512) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA512); #endif #ifdef HWCAP_SHA3 - if (hwCap & HWCAP_SHA3) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA3); +// if (hwCap & HWCAP_SHA3) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA3); #endif #ifdef HWCAP_ASIMD if (hwCap & HWCAP_ASIMD) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ADVSIMD); + CPUCompileFlags.Set(InstructionSet_AdvSimd); #endif #ifdef HWCAP_ASIMDRDM - if (hwCap & HWCAP_ASIMDRDM) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ADVSIMD_V81); +// if (hwCap & HWCAP_ASIMDRDM) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ADVSIMD_V81); #endif #ifdef HWCAP_ASIMDHP - if (hwCap & HWCAP_ASIMDHP) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ADVSIMD_FP16); +// if (hwCap & HWCAP_ASIMDHP) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ADVSIMD_FP16); #endif #ifdef HWCAP_SM3 - if (hwCap & HWCAP_SM3) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SM3); +// if (hwCap & HWCAP_SM3) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SM3); #endif #ifdef HWCAP_SM4 - if (hwCap & HWCAP_SM4) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SM4); +// if (hwCap & HWCAP_SM4) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SM4); #endif #ifdef HWCAP_SVE - if (hwCap & HWCAP_SVE) - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SVE); +// if (hwCap & HWCAP_SVE) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SVE); #endif #else // !HAVE_AUXV_HWCAP_H // CoreCLR SIMD and FP support is included in ARM64 baseline // On exceptional basis platforms may leave out support, but CoreCLR does not // yet support such platforms // Set baseline flags if OS has not exposed mechanism for us to determine CPU capabilities - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ADVSIMD); - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP); + CPUCompileFlags.Set(InstructionSet_AdvSimd); +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP); #endif // HAVE_AUXV_HWCAP_H #endif // defined(HOST_ARM64) + CPUCompileFlags.Set64BitInstructionSetVariants(); } diff --git a/src/coreclr/src/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs b/src/coreclr/src/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs new file mode 100644 index 00000000000000..aff37abdf06aca --- /dev/null +++ b/src/coreclr/src/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs @@ -0,0 +1,134 @@ + +// 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. + +// DO NOT EDIT THIS FILE! IT IS AUTOGENERATED +// FROM /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +// using /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat + +using System; +using System.Runtime.InteropServices; +using Internal.TypeSystem; + +namespace Internal.ReadyToRunConstants +{ + public enum ReadyToRunInstructionSet + { + Sse=1, + Sse2=2, + Sse3=3, + Ssse3=4, + Sse41=5, + Sse42=6, + Avx=7, + Avx2=8, + Aes=9, + Bmi1=10, + Bmi2=11, + Fma=12, + Lzcnt=13, + Pclmulqdq=14, + Popcnt=15, + ArmBase=16, + AdvSimd=17, + Crc32=18, + Sha1=19, + Sha256=20, + Atomics=21, + + } + + public static class ReadyToRunInstructionSetHelper + { + ReadyToRunInstructionSet? R2RInstructionSetFromJitInstructionSet(TargetArchitecture architecture, Internal.JitInterface.InstructionSet instructionSet) + { + switch (architecture) + { + + case TargetArchitecture.ARM64: + { + switch (instructionSet) + { + case InstructionSet.ARM64_ArmBase: return ReadyToRunInstructionSet.ArmBase; + case InstructionSet.ARM64_ArmBase_Arm64: return ReadyToRunInstructionSet.ArmBase; + case InstructionSet.ARM64_AdvSimd: return ReadyToRunInstructionSet.AdvSimd; + case InstructionSet.ARM64_AdvSimd_Arm64: return ReadyToRunInstructionSet.AdvSimd; + case InstructionSet.ARM64_Aes: return ReadyToRunInstructionSet.Aes; + case InstructionSet.ARM64_Crc32: return ReadyToRunInstructionSet.Crc32; + case InstructionSet.ARM64_Crc32_Arm64: return ReadyToRunInstructionSet.Crc32; + case InstructionSet.ARM64_Sha1: return ReadyToRunInstructionSet.Sha1; + case InstructionSet.ARM64_Sha256: return ReadyToRunInstructionSet.Sha256; + case InstructionSet.ARM64_Atomics: return ReadyToRunInstructionSet.Atomics; + case InstructionSet.ARM64_Vector64: return null; + case InstructionSet.ARM64_Vector128: return null; + + default: throw new Exception("Unknown instruction set"); + } + } + + case TargetArchitecture.X64: + { + switch (instructionSet) + { + case InstructionSet.X64_SSE: return ReadyToRunInstructionSet.Sse; + case InstructionSet.X64_SSE_X64: return ReadyToRunInstructionSet.Sse; + case InstructionSet.X64_SSE2: return ReadyToRunInstructionSet.Sse2; + case InstructionSet.X64_SSE2_X64: return ReadyToRunInstructionSet.Sse2; + case InstructionSet.X64_SSE3: return ReadyToRunInstructionSet.Sse3; + case InstructionSet.X64_SSSE3: return ReadyToRunInstructionSet.Ssse3; + case InstructionSet.X64_SSE41: return ReadyToRunInstructionSet.Sse41; + case InstructionSet.X64_SSE41_X64: return ReadyToRunInstructionSet.Sse41; + case InstructionSet.X64_SSE42: return ReadyToRunInstructionSet.Sse42; + case InstructionSet.X64_SSE42_X64: return ReadyToRunInstructionSet.Sse42; + case InstructionSet.X64_AVX: return ReadyToRunInstructionSet.Avx; + case InstructionSet.X64_AVX2: return ReadyToRunInstructionSet.Avx2; + case InstructionSet.X64_AES: return ReadyToRunInstructionSet.Aes; + case InstructionSet.X64_BMI1: return ReadyToRunInstructionSet.Bmi1; + case InstructionSet.X64_BMI1_X64: return ReadyToRunInstructionSet.Bmi1; + case InstructionSet.X64_BMI2: return ReadyToRunInstructionSet.Bmi2; + case InstructionSet.X64_BMI2_X64: return ReadyToRunInstructionSet.Bmi2; + case InstructionSet.X64_FMA: return ReadyToRunInstructionSet.Fma; + case InstructionSet.X64_LZCNT: return ReadyToRunInstructionSet.Lzcnt; + case InstructionSet.X64_LZCNT_X64: return ReadyToRunInstructionSet.Lzcnt; + case InstructionSet.X64_PCLMULQDQ: return ReadyToRunInstructionSet.Pclmulqdq; + case InstructionSet.X64_POPCNT: return ReadyToRunInstructionSet.Popcnt; + case InstructionSet.X64_POPCNT_X64: return ReadyToRunInstructionSet.Popcnt; + case InstructionSet.X64_Vector128: return null; + case InstructionSet.X64_Vector256: return null; + + default: throw new Exception("Unknown instruction set"); + } + } + + case TargetArchitecture.X86: + { + switch (instructionSet) + { + case InstructionSet.X86_SSE: return ReadyToRunInstructionSet.Sse; + case InstructionSet.X86_SSE2: return ReadyToRunInstructionSet.Sse2; + case InstructionSet.X86_SSE3: return ReadyToRunInstructionSet.Sse3; + case InstructionSet.X86_SSSE3: return ReadyToRunInstructionSet.Ssse3; + case InstructionSet.X86_SSE41: return ReadyToRunInstructionSet.Sse41; + case InstructionSet.X86_SSE42: return ReadyToRunInstructionSet.Sse42; + case InstructionSet.X86_AVX: return ReadyToRunInstructionSet.Avx; + case InstructionSet.X86_AVX2: return ReadyToRunInstructionSet.Avx2; + case InstructionSet.X86_AES: return ReadyToRunInstructionSet.Aes; + case InstructionSet.X86_BMI1: return ReadyToRunInstructionSet.Bmi1; + case InstructionSet.X86_BMI2: return ReadyToRunInstructionSet.Bmi2; + case InstructionSet.X86_FMA: return ReadyToRunInstructionSet.Fma; + case InstructionSet.X86_LZCNT: return ReadyToRunInstructionSet.Lzcnt; + case InstructionSet.X86_PCLMULQDQ: return ReadyToRunInstructionSet.Pclmulqdq; + case InstructionSet.X86_POPCNT: return ReadyToRunInstructionSet.Popcnt; + case InstructionSet.X86_Vector128: return null; + case InstructionSet.X86_Vector256: return null; + + default: throw new Exception("Unknown instruction set"); + } + } + + default: throw new Exception("Unknown architecture"); + } + } + } +} diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs index 1fadcd5cda5f1c..5dfeee4a7676e9 100644 --- a/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs @@ -2854,13 +2854,36 @@ private uint getJitFlags(ref CORJIT_FLAGS flags, uint sizeInBytes) if (targetArchitecture == TargetArchitecture.ARM && !_compilation.TypeSystemContext.Target.IsWindows) flags.Set(CorJitFlag.CORJIT_FLAG_RELATIVE_CODE_RELOCS); - if ((targetArchitecture == TargetArchitecture.X86 - || targetArchitecture == TargetArchitecture.X64) + if (targetArchitecture == TargetArchitecture.X86) + { + flags.Set(InstructionSet.X86_SSE); + flags.Set(InstructionSet.X86_SSE2); +#if !READYTORUN + // This list needs to match the list of intrinsics we can generate detection code for + // in HardwareIntrinsicHelpers.EmitIsSupportedIL. +#else + // For ReadyToRun, this list needs to match up with the behavior of FilterNamedIntrinsicMethodAttribs + // In particular, that this list of supported hardware will not generate non-SSE2 safe instruction + // sequences when paired with the behavior in FilterNamedIntrinsicMethodAttribs + if (isMethodDefinedInCoreLib()) +#endif + { + flags.Set(InstructionSet.X86_AES); + flags.Set(InstructionSet.X86_PCLMULQDQ); + flags.Set(InstructionSet.X86_SSE3); + flags.Set(InstructionSet.X86_SSSE3); + flags.Set(InstructionSet.X86_LZCNT); #if READYTORUN - && isMethodDefinedInCoreLib() + flags.Set(InstructionSet.X86_SSE41); + flags.Set(InstructionSet.X86_SSE42); + flags.Set(InstructionSet.X86_POPCNT); #endif - ) + } + } + else if (targetArchitecture == TargetArchitecture.X64) { + flags.Set(InstructionSet.X64_SSE); + flags.Set(InstructionSet.X64_SSE2); #if !READYTORUN // This list needs to match the list of intrinsics we can generate detection code for // in HardwareIntrinsicHelpers.EmitIsSupportedIL. @@ -2868,19 +2891,29 @@ private uint getJitFlags(ref CORJIT_FLAGS flags, uint sizeInBytes) // For ReadyToRun, this list needs to match up with the behavior of FilterNamedIntrinsicMethodAttribs // In particular, that this list of supported hardware will not generate non-SSE2 safe instruction // sequences when paired with the behavior in FilterNamedIntrinsicMethodAttribs + if (isMethodDefinedInCoreLib()) #endif - flags.Set(CorJitFlag.CORJIT_FLAG_USE_AES); - flags.Set(CorJitFlag.CORJIT_FLAG_USE_PCLMULQDQ); - flags.Set(CorJitFlag.CORJIT_FLAG_USE_SSE3); - flags.Set(CorJitFlag.CORJIT_FLAG_USE_SSSE3); - flags.Set(CorJitFlag.CORJIT_FLAG_USE_LZCNT); + { + flags.Set(InstructionSet.X64_AES); + flags.Set(InstructionSet.X64_PCLMULQDQ); + flags.Set(InstructionSet.X64_SSE3); + flags.Set(InstructionSet.X64_SSSE3); + flags.Set(InstructionSet.X64_LZCNT); #if READYTORUN - flags.Set(CorJitFlag.CORJIT_FLAG_USE_SSE41); - flags.Set(CorJitFlag.CORJIT_FLAG_USE_SSE42); - flags.Set(CorJitFlag.CORJIT_FLAG_USE_POPCNT); + flags.Set(InstructionSet.X64_SSE41); + flags.Set(InstructionSet.X64_SSE42); + flags.Set(InstructionSet.X64_POPCNT); #endif + } + } + else if (targetArchitecture == TargetArchitecture.ARM64) + { + flags.Set(InstructionSet.ARM64_ArmBase); + flags.Set(InstructionSet.ARM64_AdvSimd); } + flags.Set64BitInstructionSetVariants(targetArchitecture); + if (this.MethodBeingCompiled.IsNativeCallable) { #if READYTORUN diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoInstructionSet.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoInstructionSet.cs new file mode 100644 index 00000000000000..470faeb0713baa --- /dev/null +++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoInstructionSet.cs @@ -0,0 +1,317 @@ + +// 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. + +// DO NOT EDIT THIS FILE! IT IS AUTOGENERATED +// FROM /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +// using /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Internal.TypeSystem; + +namespace Internal.JitInterface +{ + public enum InstructionSet + { + ILLEGAL = 0, + NONE = 63, + ARM64_ArmBase=1, + ARM64_ArmBase_Arm64=2, + ARM64_AdvSimd=3, + ARM64_AdvSimd_Arm64=4, + ARM64_Aes=5, + ARM64_Crc32=6, + ARM64_Crc32_Arm64=7, + ARM64_Sha1=8, + ARM64_Sha256=9, + ARM64_Atomics=10, + ARM64_Vector64=11, + ARM64_Vector128=12, + X64_SSE=1, + X64_SSE2=2, + X64_SSE3=3, + X64_SSSE3=4, + X64_SSE41=5, + X64_SSE42=6, + X64_AVX=7, + X64_AVX2=8, + X64_AES=9, + X64_BMI1=10, + X64_BMI2=11, + X64_FMA=12, + X64_LZCNT=13, + X64_PCLMULQDQ=14, + X64_POPCNT=15, + X64_Vector128=16, + X64_Vector256=17, + X64_BMI1_X64=18, + X64_BMI2_X64=19, + X64_LZCNT_X64=20, + X64_POPCNT_X64=21, + X64_SSE_X64=22, + X64_SSE2_X64=23, + X64_SSE41_X64=24, + X64_SSE42_X64=25, + X86_SSE=1, + X86_SSE2=2, + X86_SSE3=3, + X86_SSSE3=4, + X86_SSE41=5, + X86_SSE42=6, + X86_AVX=7, + X86_AVX2=8, + X86_AES=9, + X86_BMI1=10, + X86_BMI2=11, + X86_FMA=12, + X86_LZCNT=13, + X86_PCLMULQDQ=14, + X86_POPCNT=15, + X86_Vector128=16, + X86_Vector256=17, + X86_BMI1_X64=18, + X86_BMI2_X64=19, + X86_LZCNT_X64=20, + X86_POPCNT_X64=21, + X86_SSE_X64=22, + X86_SSE2_X64=23, + X86_SSE41_X64=24, + X86_SSE42_X64=25, + + } + + public struct InstructionSetFlags + { + ulong _flags; + + public void AddInstructionSet(InstructionSet instructionSet) + { + _flags = _flags | (((ulong)1) << (int)instructionSet); + } + + public void RemoveInstructionSet(InstructionSet instructionSet) + { + _flags = _flags & ~(((ulong)1) << (int)instructionSet); + } + + public bool HasInstructionSet(InstructionSet instructionSet) + { + return (_flags & (((ulong)1) << (int)instructionSet)) != 0; + } + + public bool Equals(InstructionSetFlags other) + { + return _flags == other._flags; + } + + public static InstructionSetFlags ExpandInstructionSetByImplication(TargetArchitecture architecture, InstructionSetFlags input) + { + InstructionSetFlags oldflags = input; + InstructionSetFlags resultflags = input; + do + { + oldflags = resultflags; + switch(architecture) + { + + case TargetArchitecture.ARM64: + if (resultflags.HasInstructionSet(InstructionSet.ARM64_ArmBase)) + resultflags.AddInstructionSet(InstructionSet.ARM64_ArmBase_Arm64); + if (resultflags.HasInstructionSet(InstructionSet.ARM64_AdvSimd)) + resultflags.AddInstructionSet(InstructionSet.ARM64_AdvSimd_Arm64); + if (resultflags.HasInstructionSet(InstructionSet.ARM64_Crc32)) + resultflags.AddInstructionSet(InstructionSet.ARM64_Crc32_Arm64); + if (resultflags.HasInstructionSet(InstructionSet.ARM64_AdvSimd)) + resultflags.AddInstructionSet(InstructionSet.ARM64_ArmBase); + if (resultflags.HasInstructionSet(InstructionSet.ARM64_Aes)) + resultflags.AddInstructionSet(InstructionSet.ARM64_ArmBase); + if (resultflags.HasInstructionSet(InstructionSet.ARM64_Crc32)) + resultflags.AddInstructionSet(InstructionSet.ARM64_ArmBase); + if (resultflags.HasInstructionSet(InstructionSet.ARM64_Sha1)) + resultflags.AddInstructionSet(InstructionSet.ARM64_ArmBase); + if (resultflags.HasInstructionSet(InstructionSet.ARM64_Sha256)) + resultflags.AddInstructionSet(InstructionSet.ARM64_ArmBase); + break; + + case TargetArchitecture.X64: + if (resultflags.HasInstructionSet(InstructionSet.X64_SSE)) + resultflags.AddInstructionSet(InstructionSet.X64_SSE_X64); + if (resultflags.HasInstructionSet(InstructionSet.X64_SSE2)) + resultflags.AddInstructionSet(InstructionSet.X64_SSE2_X64); + if (resultflags.HasInstructionSet(InstructionSet.X64_SSE41)) + resultflags.AddInstructionSet(InstructionSet.X64_SSE41_X64); + if (resultflags.HasInstructionSet(InstructionSet.X64_SSE42)) + resultflags.AddInstructionSet(InstructionSet.X64_SSE42_X64); + if (resultflags.HasInstructionSet(InstructionSet.X64_BMI1)) + resultflags.AddInstructionSet(InstructionSet.X64_BMI1_X64); + if (resultflags.HasInstructionSet(InstructionSet.X64_BMI2)) + resultflags.AddInstructionSet(InstructionSet.X64_BMI2_X64); + if (resultflags.HasInstructionSet(InstructionSet.X64_LZCNT)) + resultflags.AddInstructionSet(InstructionSet.X64_LZCNT_X64); + if (resultflags.HasInstructionSet(InstructionSet.X64_POPCNT)) + resultflags.AddInstructionSet(InstructionSet.X64_POPCNT_X64); + if (resultflags.HasInstructionSet(InstructionSet.X64_SSE2)) + resultflags.AddInstructionSet(InstructionSet.X64_SSE); + if (resultflags.HasInstructionSet(InstructionSet.X64_SSE3)) + resultflags.AddInstructionSet(InstructionSet.X64_SSE2); + if (resultflags.HasInstructionSet(InstructionSet.X64_SSSE3)) + resultflags.AddInstructionSet(InstructionSet.X64_SSE3); + if (resultflags.HasInstructionSet(InstructionSet.X64_SSE41)) + resultflags.AddInstructionSet(InstructionSet.X64_SSSE3); + if (resultflags.HasInstructionSet(InstructionSet.X64_SSE42)) + resultflags.AddInstructionSet(InstructionSet.X64_SSE41); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX)) + resultflags.AddInstructionSet(InstructionSet.X64_SSE42); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX2)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX); + if (resultflags.HasInstructionSet(InstructionSet.X64_AES)) + resultflags.AddInstructionSet(InstructionSet.X64_SSE2); + if (resultflags.HasInstructionSet(InstructionSet.X64_BMI1)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX); + if (resultflags.HasInstructionSet(InstructionSet.X64_BMI2)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX); + if (resultflags.HasInstructionSet(InstructionSet.X64_FMA)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX); + if (resultflags.HasInstructionSet(InstructionSet.X64_PCLMULQDQ)) + resultflags.AddInstructionSet(InstructionSet.X64_SSE2); + if (resultflags.HasInstructionSet(InstructionSet.X64_POPCNT)) + resultflags.AddInstructionSet(InstructionSet.X64_SSE42); + break; + + case TargetArchitecture.X86: + if (resultflags.HasInstructionSet(InstructionSet.X86_SSE2)) + resultflags.AddInstructionSet(InstructionSet.X86_SSE); + if (resultflags.HasInstructionSet(InstructionSet.X86_SSE3)) + resultflags.AddInstructionSet(InstructionSet.X86_SSE2); + if (resultflags.HasInstructionSet(InstructionSet.X86_SSSE3)) + resultflags.AddInstructionSet(InstructionSet.X86_SSE3); + if (resultflags.HasInstructionSet(InstructionSet.X86_SSE41)) + resultflags.AddInstructionSet(InstructionSet.X86_SSSE3); + if (resultflags.HasInstructionSet(InstructionSet.X86_SSE42)) + resultflags.AddInstructionSet(InstructionSet.X86_SSE41); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX)) + resultflags.AddInstructionSet(InstructionSet.X86_SSE42); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX2)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX); + if (resultflags.HasInstructionSet(InstructionSet.X86_AES)) + resultflags.AddInstructionSet(InstructionSet.X86_SSE2); + if (resultflags.HasInstructionSet(InstructionSet.X86_BMI1)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX); + if (resultflags.HasInstructionSet(InstructionSet.X86_BMI2)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX); + if (resultflags.HasInstructionSet(InstructionSet.X86_FMA)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX); + if (resultflags.HasInstructionSet(InstructionSet.X86_PCLMULQDQ)) + resultflags.AddInstructionSet(InstructionSet.X86_SSE2); + if (resultflags.HasInstructionSet(InstructionSet.X86_POPCNT)) + resultflags.AddInstructionSet(InstructionSet.X86_SSE42); + break; + + } + } while (!oldflags.Equals(resultflags)); + return resultflags; + } + + public static IEnumerable> ArchitectureToValidInstructionSets(TargetArchitecture architecture) + { + switch (architecture) + { + + case TargetArchitecture.ARM64: + yield return new KeyValuePair("ArmBase", InstructionSet.ARM64_ArmBase); + yield return new KeyValuePair("AdvSimd", InstructionSet.ARM64_AdvSimd); + yield return new KeyValuePair("Aes", InstructionSet.ARM64_Aes); + yield return new KeyValuePair("Crc32", InstructionSet.ARM64_Crc32); + yield return new KeyValuePair("Sha1", InstructionSet.ARM64_Sha1); + yield return new KeyValuePair("Sha256", InstructionSet.ARM64_Sha256); + yield return new KeyValuePair("Atomics", InstructionSet.ARM64_Atomics); + yield return new KeyValuePair("Vector64", InstructionSet.ARM64_Vector64); + yield return new KeyValuePair("Vector128", InstructionSet.ARM64_Vector128); + break; + + case TargetArchitecture.X64: + yield return new KeyValuePair("Sse", InstructionSet.X64_SSE); + yield return new KeyValuePair("Sse2", InstructionSet.X64_SSE2); + yield return new KeyValuePair("Sse3", InstructionSet.X64_SSE3); + yield return new KeyValuePair("Ssse3", InstructionSet.X64_SSSE3); + yield return new KeyValuePair("Sse41", InstructionSet.X64_SSE41); + yield return new KeyValuePair("Sse42", InstructionSet.X64_SSE42); + yield return new KeyValuePair("Avx", InstructionSet.X64_AVX); + yield return new KeyValuePair("Avx2", InstructionSet.X64_AVX2); + yield return new KeyValuePair("Aes", InstructionSet.X64_AES); + yield return new KeyValuePair("Bmi1", InstructionSet.X64_BMI1); + yield return new KeyValuePair("Bmi2", InstructionSet.X64_BMI2); + yield return new KeyValuePair("Fma", InstructionSet.X64_FMA); + yield return new KeyValuePair("Lzcnt", InstructionSet.X64_LZCNT); + yield return new KeyValuePair("Pclmulqdq", InstructionSet.X64_PCLMULQDQ); + yield return new KeyValuePair("Popcnt", InstructionSet.X64_POPCNT); + yield return new KeyValuePair("Vector128", InstructionSet.X64_Vector128); + yield return new KeyValuePair("Vector256", InstructionSet.X64_Vector256); + break; + + case TargetArchitecture.X86: + yield return new KeyValuePair("Sse", InstructionSet.X86_SSE); + yield return new KeyValuePair("Sse2", InstructionSet.X86_SSE2); + yield return new KeyValuePair("Sse3", InstructionSet.X86_SSE3); + yield return new KeyValuePair("Ssse3", InstructionSet.X86_SSSE3); + yield return new KeyValuePair("Sse41", InstructionSet.X86_SSE41); + yield return new KeyValuePair("Sse42", InstructionSet.X86_SSE42); + yield return new KeyValuePair("Avx", InstructionSet.X86_AVX); + yield return new KeyValuePair("Avx2", InstructionSet.X86_AVX2); + yield return new KeyValuePair("Aes", InstructionSet.X86_AES); + yield return new KeyValuePair("Bmi1", InstructionSet.X86_BMI1); + yield return new KeyValuePair("Bmi2", InstructionSet.X86_BMI2); + yield return new KeyValuePair("Fma", InstructionSet.X86_FMA); + yield return new KeyValuePair("Lzcnt", InstructionSet.X86_LZCNT); + yield return new KeyValuePair("Pclmulqdq", InstructionSet.X86_PCLMULQDQ); + yield return new KeyValuePair("Popcnt", InstructionSet.X86_POPCNT); + yield return new KeyValuePair("Vector128", InstructionSet.X86_Vector128); + yield return new KeyValuePair("Vector256", InstructionSet.X86_Vector256); + break; + + } + } + + public void Set64BitInstructionSetVariants(TargetArchitecture architecture) + { + switch (architecture) + { + + case TargetArchitecture.ARM64: + if (HasInstructionSet(InstructionSet.ARM64_ArmBase)) + AddInstructionSet(InstructionSet.ARM64_ArmBase_Arm64); + if (HasInstructionSet(InstructionSet.ARM64_AdvSimd)) + AddInstructionSet(InstructionSet.ARM64_AdvSimd_Arm64); + if (HasInstructionSet(InstructionSet.ARM64_Crc32)) + AddInstructionSet(InstructionSet.ARM64_Crc32_Arm64); + break; + + case TargetArchitecture.X64: + if (HasInstructionSet(InstructionSet.X64_SSE)) + AddInstructionSet(InstructionSet.X64_SSE_X64); + if (HasInstructionSet(InstructionSet.X64_SSE2)) + AddInstructionSet(InstructionSet.X64_SSE2_X64); + if (HasInstructionSet(InstructionSet.X64_SSE41)) + AddInstructionSet(InstructionSet.X64_SSE41_X64); + if (HasInstructionSet(InstructionSet.X64_SSE42)) + AddInstructionSet(InstructionSet.X64_SSE42_X64); + if (HasInstructionSet(InstructionSet.X64_BMI1)) + AddInstructionSet(InstructionSet.X64_BMI1_X64); + if (HasInstructionSet(InstructionSet.X64_BMI2)) + AddInstructionSet(InstructionSet.X64_BMI2_X64); + if (HasInstructionSet(InstructionSet.X64_LZCNT)) + AddInstructionSet(InstructionSet.X64_LZCNT_X64); + if (HasInstructionSet(InstructionSet.X64_POPCNT)) + AddInstructionSet(InstructionSet.X64_POPCNT_X64); + break; + + case TargetArchitecture.X86: + break; + + } + } + } +} diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoTypes.cs index 1647c4fb75da59..64d4a0649dfa06 100644 --- a/src/coreclr/src/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoTypes.cs @@ -5,6 +5,7 @@ using System; using System.Diagnostics; using System.Runtime.InteropServices; +using Internal.TypeSystem; namespace Internal.JitInterface { @@ -1296,9 +1297,6 @@ public enum CorJitFlag : uint CORJIT_FLAG_UNUSED4 = 11, CORJIT_FLAG_UNUSED5 = 12, CORJIT_FLAG_UNUSED6 = 13, - CORJIT_FLAG_USE_AVX = 14, - CORJIT_FLAG_USE_AVX2 = 15, - CORJIT_FLAG_USE_AVX_512 = 16, CORJIT_FLAG_FEATURE_SIMD = 17, CORJIT_FLAG_MAKEFINALCODE = 18, // Use the final code generator, i.e., not the interpreter. CORJIT_FLAG_READYTORUN = 19, // Use version-resilient code generation @@ -1325,49 +1323,12 @@ public enum CorJitFlag : uint CORJIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code CORJIT_FLAG_RELATIVE_CODE_RELOCS = 41, // JIT should generate PC-relative address computations instead of EE relocation records CORJIT_FLAG_NO_INLINING = 42, // JIT should not inline any called method into this method - -#region TARGET_ARM64 - CORJIT_FLAG_HAS_ARM64_AES = 43, // ID_AA64ISAR0_EL1.AES is 1 or better - CORJIT_FLAG_HAS_ARM64_ATOMICS = 44, // ID_AA64ISAR0_EL1.Atomic is 2 or better - CORJIT_FLAG_HAS_ARM64_CRC32 = 45, // ID_AA64ISAR0_EL1.CRC32 is 1 or better - CORJIT_FLAG_HAS_ARM64_DCPOP = 46, // ID_AA64ISAR1_EL1.DPB is 1 or better - CORJIT_FLAG_HAS_ARM64_DP = 47, // ID_AA64ISAR0_EL1.DP is 1 or better - CORJIT_FLAG_HAS_ARM64_FCMA = 48, // ID_AA64ISAR1_EL1.FCMA is 1 or better - CORJIT_FLAG_HAS_ARM64_FP = 49, // ID_AA64PFR0_EL1.FP is 0 or better - CORJIT_FLAG_HAS_ARM64_FP16 = 50, // ID_AA64PFR0_EL1.FP is 1 or better - CORJIT_FLAG_HAS_ARM64_JSCVT = 51, // ID_AA64ISAR1_EL1.JSCVT is 1 or better - CORJIT_FLAG_HAS_ARM64_LRCPC = 52, // ID_AA64ISAR1_EL1.LRCPC is 1 or better - CORJIT_FLAG_HAS_ARM64_PMULL = 53, // ID_AA64ISAR0_EL1.AES is 2 or better - CORJIT_FLAG_HAS_ARM64_SHA1 = 54, // ID_AA64ISAR0_EL1.SHA1 is 1 or better - CORJIT_FLAG_HAS_ARM64_SHA256 = 55, // ID_AA64ISAR0_EL1.SHA2 is 1 or better - CORJIT_FLAG_HAS_ARM64_SHA512 = 56, // ID_AA64ISAR0_EL1.SHA2 is 2 or better - CORJIT_FLAG_HAS_ARM64_SHA3 = 57, // ID_AA64ISAR0_EL1.SHA3 is 1 or better - CORJIT_FLAG_HAS_ARM64_SIMD = 58, // ID_AA64PFR0_EL1.AdvSIMD is 0 or better - CORJIT_FLAG_HAS_ARM64_SIMD_V81 = 59, // ID_AA64ISAR0_EL1.RDM is 1 or better - CORJIT_FLAG_HAS_ARM64_SIMD_FP16 = 60, // ID_AA64PFR0_EL1.AdvSIMD is 1 or better - CORJIT_FLAG_HAS_ARM64_SM3 = 61, // ID_AA64ISAR0_EL1.SM3 is 1 or better - CORJIT_FLAG_HAS_ARM64_SM4 = 62, // ID_AA64ISAR0_EL1.SM4 is 1 or better - CORJIT_FLAG_HAS_ARM64_SVE = 63, // ID_AA64PFR0_EL1.SVE is 1 or better -#endregion - -#region x86/x64 - CORJIT_FLAG_USE_SSE3 = 43, - CORJIT_FLAG_USE_SSSE3 = 44, - CORJIT_FLAG_USE_SSE41 = 45, - CORJIT_FLAG_USE_SSE42 = 46, - CORJIT_FLAG_USE_AES = 47, - CORJIT_FLAG_USE_BMI1 = 48, - CORJIT_FLAG_USE_BMI2 = 49, - CORJIT_FLAG_USE_FMA = 50, - CORJIT_FLAG_USE_LZCNT = 51, - CORJIT_FLAG_USE_PCLMULQDQ = 52, - CORJIT_FLAG_USE_POPCNT = 53, -#endregion } public struct CORJIT_FLAGS { private UInt64 _corJitFlags; + InstructionSetFlags _instructionSetFlags; public void Reset() { @@ -1379,6 +1340,11 @@ public void Set(CorJitFlag flag) _corJitFlags |= 1UL << (int)flag; } + public void Set(InstructionSet instructionSet) + { + _instructionSetFlags.AddInstructionSet(instructionSet); + } + public void Clear(CorJitFlag flag) { _corJitFlags &= ~(1UL << (int)flag); @@ -1389,19 +1355,9 @@ public bool IsSet(CorJitFlag flag) return (_corJitFlags & (1UL << (int)flag)) != 0; } - public void Add(ref CORJIT_FLAGS other) - { - _corJitFlags |= other._corJitFlags; - } - - public void Remove(ref CORJIT_FLAGS other) - { - _corJitFlags &= ~other._corJitFlags; - } - - public bool IsEmpty() + public void Set64BitInstructionSetVariants(TargetArchitecture architecture) { - return _corJitFlags == 0; + _instructionSetFlags.Set64BitInstructionSetVariants(architecture); } } } diff --git a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt new file mode 100644 index 00000000000000..9c8404fe8969f0 --- /dev/null +++ b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt @@ -0,0 +1,81 @@ +; Define the set of instruction sets available on a platform +; Format is +; +; Add new instruction set +; instructionset,,,,, +; +; Add jit 64bit architecture specific instruction set when instruction set is available +; instructionset64bit,, +; +; Add an instruction set implication (i.e, if instruction set A is present, then instruction set B must be present too.) +; implication,,, +; +; Copy instruction sets defined for other architecture at this point in the file. +; copyinstructionsets,, + +; Definition of X86 instruction sets + +definearch ,X86 ,32Bit ,X64 +instructionset ,X86 ,Sse , ,1 ,SSE +instructionset ,X86 ,Sse2 , ,2 ,SSE2 +implication ,X86 ,SSE2 ,SSE +instructionset ,X86 ,Sse3 , ,3 ,SSE3 +implication ,X86 ,SSE3 ,SSE2 +instructionset ,X86 ,Ssse3 , ,4 ,SSSE3 +implication ,X86 ,SSSE3 ,SSE3 +instructionset ,X86 ,Sse41 , ,5 ,SSE41 +implication ,X86 ,SSE41 ,SSSE3 +instructionset ,X86 ,Sse42 , ,6 ,SSE42 +implication ,X86 ,SSE42 ,SSE41 +instructionset ,X86 ,Avx , ,7 ,AVX +implication ,X86 ,AVX ,SSE42 +instructionset ,X86 ,Avx2 , ,8 ,AVX2 +implication ,X86 ,AVX2 ,AVX +instructionset ,X86 ,Aes , ,9 ,AES +implication ,X86 ,AES ,SSE2 +instructionset ,X86 ,Bmi1 , ,10 ,BMI1 +implication ,X86 ,BMI1 ,AVX +instructionset ,X86 ,Bmi2 , ,11 ,BMI2 +implication ,X86 ,BMI2 ,AVX +instructionset ,X86 ,Fma , ,12 ,FMA +implication ,X86 ,FMA ,AVX +instructionset ,X86 ,Lzcnt , ,13 ,LZCNT +instructionset ,X86 ,Pclmulqdq , ,14 ,PCLMULQDQ +implication ,X86 ,PCLMULQDQ ,SSE2 +instructionset ,X86 ,Popcnt , ,15 ,POPCNT +implication ,X86 ,POPCNT ,SSE42 +instructionset ,X86 , , , ,Vector128 +instructionset ,X86 , , , ,Vector256 + +; Definition of X64 instruction sets (Define ) +definearch ,X64 ,64Bit ,X64 +instructionset64bit,X86 ,BMI1 +instructionset64bit,X86 ,BMI2 +instructionset64bit,X86 ,LZCNT +instructionset64bit,X86 ,POPCNT +instructionset64bit,X86 ,SSE +instructionset64bit,X86 ,SSE2 +instructionset64bit,X86 ,SSE41 +instructionset64bit,X86 ,SSE42 + +copyinstructionsets,X86 ,X64 + +; Definition of the Arm64 instruction sets +definearch ,ARM64 ,64Bit ,Arm64 +instructionset ,ARM64 ,ArmBase , ,16 ,ArmBase +instructionset64bit,ARM64 ,ArmBase +instructionset ,ARM64 ,AdvSimd , ,17 ,AdvSimd +instructionset64bit,ARM64 ,AdvSimd +implication ,ARM64 ,AdvSimd ,ArmBase +instructionset ,ARM64 ,Aes , ,9 ,Aes +implication ,ARM64 ,Aes ,ArmBase +instructionset ,ARM64 ,Crc32 , ,18 ,Crc32 +instructionset64bit,ARM64 ,Crc32 +implication ,ARM64 ,Crc32 ,ArmBase +instructionset ,ARM64 ,Sha1 , ,19 ,Sha1 +implication ,ARM64 ,Sha1 ,ArmBase +instructionset ,ARM64 ,Sha256 , ,20 ,Sha256 +implication ,ARM64 ,Sha256 ,ArmBase +instructionset ,ARM64 , ,Atomics ,21 ,Atomics +instructionset ,ARM64 , , , ,Vector64 +instructionset ,ARM64 , , , ,Vector128 diff --git a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs new file mode 100644 index 00000000000000..3d5ea118732e30 --- /dev/null +++ b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs @@ -0,0 +1,645 @@ +// 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; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using System.Diagnostics; + +namespace Thunkerator +{ + public class InstructionSetGenerator + { + class InstructionSetInfo + { + public string Architecture { get; } + public string ManagedName { get; } + public string R2rName { get; } + public string R2rNumericValue { get; } + public string JitName { get; } + + public InstructionSetInfo(string architecture, string managedName, string r2rName, string r2rNumericValue, string jitName) + { + Architecture = architecture; + ManagedName = managedName; + R2rName = String.IsNullOrEmpty(r2rName) ? managedName : r2rName; + R2rNumericValue = r2rNumericValue; + JitName = jitName; + } + + public InstructionSetInfo(string architecture, InstructionSetInfo similarInstructionSet) + { + Architecture = architecture; + ManagedName = similarInstructionSet.ManagedName; + R2rName = similarInstructionSet.R2rName; + R2rNumericValue = similarInstructionSet.R2rNumericValue; + JitName = similarInstructionSet.JitName; + } + + public string PublicName + { + get + { + if (!String.IsNullOrEmpty(ManagedName)) + return ManagedName; + else if (!String.IsNullOrEmpty(R2rName)) + return R2rName; + else + return JitName; + } + } + } + + class InstructionSetImplication + { + public string Architecture { get; } + public string JitName { get; } + public string ImpliedJitName { get; } + + public InstructionSetImplication(string architecture, string jitName, string impliedJitName) + { + Architecture = architecture; + JitName = jitName; + ImpliedJitName = impliedJitName; + } + + public InstructionSetImplication(string architecture, InstructionSetImplication similarInstructionSet) + { + Architecture = architecture; + ImpliedJitName = similarInstructionSet.ImpliedJitName; + JitName = similarInstructionSet.JitName; + } + } + + List _instructionSets = new List(); + List _implications = new List(); + Dictionary> _64bitVariants = new Dictionary>(); + SortedDictionary _r2rNamesByName = new SortedDictionary(); + SortedDictionary _r2rNamesByNumber = new SortedDictionary(); + SortedSet _architectures = new SortedSet(); + Dictionary> _architectureJitNames = new Dictionary>(); + HashSet _64BitArchitectures = new HashSet(); + Dictionary _64BitVariantArchitectureJitNameSuffix = new Dictionary(); + + void ArchitectureEncountered(string arch) + { + if (!_64bitVariants.ContainsKey(arch)) + _64bitVariants.Add(arch, new HashSet()); + _architectures.Add(arch); + if (!_architectureJitNames.ContainsKey(arch)) + _architectureJitNames.Add(arch, new List()); + } + + void ValidateArchitectureEncountered(string arch) + { + if (!_architectures.Contains(arch)) + throw new Exception("Architecture not defined"); + } + + private string ArchToIfDefArch(string arch) + { + if (arch == "X64") + return "AMD64"; + return arch; + } + + + private string ArchToInstructionSetSuffixArch(string arch) + { + return _64BitVariantArchitectureJitNameSuffix[arch]; + } + + public bool ParseInput(TextReader tr) + { + int currentLineIndex = 1; + for (string currentLine = tr.ReadLine(); currentLine != null; currentLine = tr.ReadLine(), currentLineIndex++) + { + try + { + if (currentLine.Length == 0) + { + continue; // Its an empty line, ignore + } + + if (currentLine[0] == ';') + { + continue; // Its a comment + } + + string[] command = currentLine.Split(','); + for (int i = 0; i < command.Length; i++) + { + command[i] = command[i].Trim(); + } + switch(command[0]) + { + case "definearch": + if (command.Length != 4) + throw new Exception($"Incorrect number of args for definearch {command.Length}"); + ArchitectureEncountered(command[1]); + if (command[2] == "64Bit") + { + _64BitArchitectures.Add(command[1]); + } + else if (command[2] != "32Bit") + { + throw new Exception("Architecture must be 32Bit or 64Bit"); + } + _64BitVariantArchitectureJitNameSuffix[command[1]] = command[3]; + break; + case "instructionset": + if (command.Length != 6) + throw new Exception("Incorrect number of args for instructionset"); + ValidateArchitectureEncountered(command[1]); + _architectureJitNames[command[1]].Add(command[5]); + _instructionSets.Add(new InstructionSetInfo(command[1],command[2],command[3],command[4],command[5])); + break; + case "instructionset64bit": + if (command.Length != 3) + throw new Exception("Incorrect number of args for instructionset"); + ValidateArchitectureEncountered(command[1]); + _64bitVariants[command[1]].Add(command[2]); + _architectureJitNames[command[1]].Add(command[2] + "_" + ArchToInstructionSetSuffixArch(command[1])); + break; + case "implication": + if (command.Length != 4) + throw new Exception("Incorrect number of args for instructionset"); + ValidateArchitectureEncountered(command[1]); + _implications.Add(new InstructionSetImplication(command[1],command[2], command[3])); + break; + case "copyinstructionsets": + if (command.Length != 3) + throw new Exception("Incorrect number of args for instructionset"); + ValidateArchitectureEncountered(command[1]); + ValidateArchitectureEncountered(command[2]); + string arch = command[1]; + string targetarch = command[2]; + foreach (var val in _instructionSets.ToArray()) + { + if (val.Architecture != arch) + continue; + _instructionSets.Add(new InstructionSetInfo(targetarch, val)); + _architectureJitNames[targetarch].Add(val.JitName); + } + foreach (var val in _implications.ToArray()) + { + if (val.Architecture != arch) + continue; + _implications.Add(new InstructionSetImplication(targetarch, val)); + } + foreach (var val in _64bitVariants[arch]) + { + _64bitVariants[targetarch].Add(val); + _architectureJitNames[targetarch].Add(val + "_" + ArchToInstructionSetSuffixArch(targetarch)); + } + break; + default: + throw new Exception("Unknown command"); + } + } + catch (Exception e) + { + Console.Error.WriteLine("Error parsing line {0} : {1}", currentLineIndex, e.Message); + return false; + } + } + + foreach (var instructionSet in _instructionSets) + { + if (!String.IsNullOrEmpty(instructionSet.R2rName)) + { + int r2rValue = Int32.Parse(instructionSet.R2rNumericValue); + if (_r2rNamesByName.ContainsKey(instructionSet.R2rName)) + { + if (_r2rNamesByName[instructionSet.R2rName] != r2rValue) + throw new Exception("R2R name/number mismatch"); + } + else + { + _r2rNamesByName.Add(instructionSet.R2rName, r2rValue); + _r2rNamesByNumber.Add(r2rValue, instructionSet.R2rName); + } + } + } + + foreach (var architectureInfo in _architectureJitNames) + { + if (architectureInfo.Value.Count > 62) + { + throw new Exception("Too many instruction sets added. Scheme of using uint64_t as instruction mask will need updating"); + } + } + + return true; + } + + public void WriteManagedReadyToRunInstructionSet(TextWriter tr) + { + // Write header + tr.Write(@" +// 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. + +// DO NOT EDIT THIS FILE! IT IS AUTOGENERATED +// FROM /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +// using /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat + +using System; +using System.Runtime.InteropServices; +using Internal.TypeSystem; + +namespace Internal.ReadyToRunConstants +{ + public enum ReadyToRunInstructionSet + { +"); + + foreach (var r2rEntry in _r2rNamesByNumber) + { + tr.WriteLine($" {r2rEntry.Value}={r2rEntry.Key},"); + } + tr.Write(@" + } + + public static class ReadyToRunInstructionSetHelper + { + ReadyToRunInstructionSet? R2RInstructionSetFromJitInstructionSet(TargetArchitecture architecture, Internal.JitInterface.InstructionSet instructionSet) + { + switch (architecture) + { +"); + foreach (string architecture in _architectures) + { + tr.Write($@" + case TargetArchitecture.{architecture}: + {{ + switch (instructionSet) + {{ +"); + foreach (var instructionSet in _instructionSets) + { + if (instructionSet.Architecture != architecture) continue; + + string r2rEnumerationValue; + if (!String.IsNullOrEmpty(instructionSet.R2rName)) + r2rEnumerationValue = $"ReadyToRunInstructionSet.{instructionSet.R2rName}"; + else + r2rEnumerationValue = $"null"; + + tr.WriteLine($" case InstructionSet.{architecture}_{instructionSet.JitName}: return {r2rEnumerationValue};"); + if (_64BitArchitectures.Contains(architecture) && _64bitVariants[architecture].Contains(instructionSet.JitName)) + tr.WriteLine($" case InstructionSet.{architecture}_{instructionSet.JitName}_{ArchToInstructionSetSuffixArch(architecture)}: return {r2rEnumerationValue};"); + } + + tr.Write(@" + default: throw new Exception(""Unknown instruction set""); + } + } +"); + } + + tr.Write(@" + default: throw new Exception(""Unknown architecture""); + } + } + } +} +"); + } + + public void WriteManagedJitInstructionSet(TextWriter tr) + { + // Write header + tr.Write(@" +// 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. + +// DO NOT EDIT THIS FILE! IT IS AUTOGENERATED +// FROM /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +// using /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Internal.TypeSystem; + +namespace Internal.JitInterface +{ + public enum InstructionSet + { + ILLEGAL = 0, + NONE = 63, +"); + foreach (string architecture in _architectures) + { + int counter = 1; + foreach (var jitName in _architectureJitNames[architecture]) + { + tr.WriteLine($" {architecture}_{jitName}={counter++},"); + } + } + + tr.Write(@" + } + + public struct InstructionSetFlags + { + ulong _flags; + + public void AddInstructionSet(InstructionSet instructionSet) + { + _flags = _flags | (((ulong)1) << (int)instructionSet); + } + + public void RemoveInstructionSet(InstructionSet instructionSet) + { + _flags = _flags & ~(((ulong)1) << (int)instructionSet); + } + + public bool HasInstructionSet(InstructionSet instructionSet) + { + return (_flags & (((ulong)1) << (int)instructionSet)) != 0; + } + + public bool Equals(InstructionSetFlags other) + { + return _flags == other._flags; + } + + public static InstructionSetFlags ExpandInstructionSetByImplication(TargetArchitecture architecture, InstructionSetFlags input) + { + InstructionSetFlags oldflags = input; + InstructionSetFlags resultflags = input; + do + { + oldflags = resultflags; + switch(architecture) + { +"); + foreach (string architecture in _architectures) + { + tr.Write($@" + case TargetArchitecture.{architecture}: +"); + foreach (var instructionSet in _instructionSets) + { + if (instructionSet.Architecture != architecture) continue; + if (_64BitArchitectures.Contains(architecture) && _64bitVariants[architecture].Contains(instructionSet.JitName)) + AddImplication(architecture, instructionSet.JitName, $"{instructionSet.JitName}_{ArchToInstructionSetSuffixArch(architecture)}"); + } + foreach (var implication in _implications) + { + if (implication.Architecture != architecture) continue; + AddImplication(architecture, implication.JitName, implication.ImpliedJitName); + } + tr.WriteLine(" break;"); + } + + tr.Write(@" + } + } while (!oldflags.Equals(resultflags)); + return resultflags; + } + + public static IEnumerable> ArchitectureToValidInstructionSets(TargetArchitecture architecture) + { + switch (architecture) + { +"); + foreach (string architecture in _architectures) + { + tr.Write($@" + case TargetArchitecture.{architecture}: +"); + foreach (var instructionSet in _instructionSets) + { + if (instructionSet.Architecture != architecture) continue; + tr.WriteLine($" yield return new KeyValuePair(\"{instructionSet.PublicName}\", InstructionSet.{architecture}_{instructionSet.JitName});"); + } + tr.WriteLine(" break;"); + } + tr.Write(@" + } + } + + public void Set64BitInstructionSetVariants(TargetArchitecture architecture) + { + switch (architecture) + { +"); + foreach (string architecture in _architectures) + { + tr.Write($@" + case TargetArchitecture.{architecture}: +"); + foreach (var instructionSet in _instructionSets) + { + if (instructionSet.Architecture != architecture) continue; + + if (_64BitArchitectures.Contains(architecture) && _64bitVariants[architecture].Contains(instructionSet.JitName)) + { + tr.WriteLine($" if (HasInstructionSet(InstructionSet.{architecture}_{instructionSet.JitName}))"); + tr.WriteLine($" AddInstructionSet(InstructionSet.{architecture}_{instructionSet.JitName}_{ArchToInstructionSetSuffixArch(architecture)});"); + } + } + + tr.WriteLine(" break;"); + } + tr.Write(@" + } + } + } +} +"); + return; + void AddImplication(string architecture, string jitName, string impliedJitName) + { + tr.WriteLine($" if (resultflags.HasInstructionSet(InstructionSet.{architecture}_{jitName}))"); + tr.WriteLine($" resultflags.AddInstructionSet(InstructionSet.{architecture}_{impliedJitName});"); + } + } + + public void WriteNativeCorInfoInstructionSet(TextWriter tr) + { + // Write header + tr.Write(@" +// 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. + +// DO NOT EDIT THIS FILE! IT IS AUTOGENERATED +// FROM /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +// using /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat + +#ifndef CORINFOINSTRUCTIONSET_H +#define CORINFOINSTRUCTIONSET_H + +enum CORINFO_InstructionSet +{ + InstructionSet_ILLEGAL = 0, + InstructionSet_NONE = 63, +"); + foreach (string architecture in _architectures) + { + tr.WriteLine($"#ifdef TARGET_{ArchToIfDefArch(architecture)}"); + int counter = 1; + foreach (var jitName in _architectureJitNames[architecture]) + { + tr.WriteLine($" InstructionSet_{jitName}={counter++},"); + } + tr.WriteLine($"#endif // TARGET_{ArchToIfDefArch(architecture)}"); + } + tr.Write(@" +}; + +struct CORINFO_InstructionSetFlags +{ +private: + uint64_t _flags = 0; +public: + void AddInstructionSet(CORINFO_InstructionSet instructionSet) + { + _flags = _flags | (((uint64_t)1) << instructionSet); + } + + void RemoveInstructionSet(CORINFO_InstructionSet instructionSet) + { + _flags = _flags & ~(((uint64_t)1) << instructionSet); + } + + bool HasInstructionSet(CORINFO_InstructionSet instructionSet) const + { + return _flags & (((uint64_t)1) << instructionSet); + } + + bool Equals(CORINFO_InstructionSetFlags other) const + { + return _flags == other._flags; + } + + void Add(CORINFO_InstructionSetFlags other) + { + _flags |= other._flags; + } + + bool IsEmpty() const + { + return _flags == 0; + } + + void Reset() + { + _flags = 0; + } + + void Set64BitInstructionSetVariants() + { +"); + foreach (string architecture in _architectures) + { + tr.WriteLine($"#ifdef TARGET_{ArchToIfDefArch(architecture)}"); + foreach (var instructionSet in _instructionSets) + { + if (instructionSet.Architecture != architecture) continue; + + if (_64BitArchitectures.Contains(architecture) && _64bitVariants[architecture].Contains(instructionSet.JitName)) + { + tr.WriteLine($" if (HasInstructionSet(InstructionSet_{instructionSet.JitName}))"); + tr.WriteLine($" AddInstructionSet(InstructionSet_{instructionSet.JitName}_{ArchToInstructionSetSuffixArch(architecture)});"); + } + } + + tr.WriteLine($"#endif // TARGET_{ArchToIfDefArch(architecture)}"); + } + tr.Write(@" + } + + uint64_t GetFlagsRaw() + { + return _flags; + } + + void SetFromFlagsRaw(uint64_t flags) + { + _flags = flags; + } +}; + +inline CORINFO_InstructionSetFlags EnsureInstructionSetFlagsAreValid(CORINFO_InstructionSetFlags input) +{ + CORINFO_InstructionSetFlags oldflags = input; + CORINFO_InstructionSetFlags resultflags = input; + do + { + oldflags = resultflags; +"); + foreach (string architecture in _architectures) + { + tr.WriteLine($"#ifdef TARGET_{ArchToIfDefArch(architecture)}"); + foreach (var instructionSet in _instructionSets) + { + if (instructionSet.Architecture != architecture) continue; + if (_64BitArchitectures.Contains(architecture) && _64bitVariants[architecture].Contains(instructionSet.JitName)) + AddImplication(architecture, instructionSet.JitName, $"{instructionSet.JitName}_{ArchToInstructionSetSuffixArch(architecture)}"); + } + foreach (var implication in _implications) + { + if (implication.Architecture != architecture) continue; + AddImplication(architecture, implication.JitName, implication.ImpliedJitName); + } + tr.WriteLine($"#endif // TARGET_{ArchToIfDefArch(architecture)}"); + } + tr.Write(@" + } while (!oldflags.Equals(resultflags)); + return resultflags; +} + + + +#endif // CORINFOINSTRUCTIONSET_H +"); + return; + + void AddImplication(string architecture, string jitName, string impliedJitName) + { + tr.WriteLine($" if (resultflags.HasInstructionSet(InstructionSet_{jitName}) && !resultflags.HasInstructionSet(InstructionSet_{impliedJitName}))"); + tr.WriteLine($" resultflags.RemoveInstructionSet(InstructionSet_{jitName});"); + } + } + + public void WriteNativeReadyToRunInstructionSet(TextWriter tr) + { + // Write header + tr.Write(@" +// 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. + +// DO NOT EDIT THIS FILE! IT IS AUTOGENERATED +// FROM /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +// using /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat + +#ifndef READYTORUNINSTRUCTIONSET_H +#define READYTORUNINSTRUCTIONSET_H +enum ReadyToRunInstructionSet +{ +"); + + foreach (var r2rEntry in _r2rNamesByNumber) + { + tr.WriteLine($" READYTORUN_INSTRUCTION_{r2rEntry.Value}={r2rEntry.Key},"); + } + tr.Write(@" +}; + +#endif // READYTORUNINSTRUCTIONSET_H +"); + } + } +} \ No newline at end of file diff --git a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/Program.cs b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/Program.cs index 78b513211cc4a0..94fa40662716d2 100644 --- a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/Program.cs +++ b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/Program.cs @@ -493,16 +493,49 @@ class JitInterfaceWrapper static void Main(string[] args) { - IEnumerable functions = ParseInput(new StreamReader(args[0])); - using (TextWriter tw = new StreamWriter(args[1])) + if (args[0] == "InstructionSetGenerator") { - Console.WriteLine("Generating {0}", args[1]); - WriteManagedThunkInterface(tw, functions); + InstructionSetGenerator generator = new InstructionSetGenerator(); + if (!generator.ParseInput(new StreamReader(args[1]))) + return; + + using (TextWriter tw = new StreamWriter(args[2])) + { + Console.WriteLine("Generating {0}", args[2]); + generator.WriteManagedReadyToRunInstructionSet(tw); + } + + using (TextWriter tw = new StreamWriter(args[3])) + { + Console.WriteLine("Generating {0}", args[3]); + generator.WriteManagedJitInstructionSet(tw); + } + + using (TextWriter tw = new StreamWriter(args[4])) + { + Console.WriteLine("Generating {0}", args[4]); + generator.WriteNativeCorInfoInstructionSet(tw); + } + + using (TextWriter tw = new StreamWriter(args[5])) + { + Console.WriteLine("Generating {0}", args[5]); + generator.WriteNativeReadyToRunInstructionSet(tw); + } } - using (TextWriter tw = new StreamWriter(args[2])) + else { - Console.WriteLine("Generating {0}", args[2]); - WriteNativeWrapperInterface(tw, functions); + IEnumerable functions = ParseInput(new StreamReader(args[0])); + using (TextWriter tw = new StreamWriter(args[1])) + { + Console.WriteLine("Generating {0}", args[1]); + WriteManagedThunkInterface(tw, functions); + } + using (TextWriter tw = new StreamWriter(args[2])) + { + Console.WriteLine("Generating {0}", args[2]); + WriteNativeWrapperInterface(tw, functions); + } } } } diff --git a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat index 46328b52d08baf..f90ce4554e37a8 100644 --- a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat +++ b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat @@ -1,2 +1,4 @@ -cd /d %~dp0 -dotnet run -- ThunkInput.txt ..\CorInfoBase.cs ..\..\..\crossgen2\jitinterface\jitinterface.h \ No newline at end of file +pushd %~dp0 +call ..\..\..\..\..\..\..\dotnet.cmd run -- ThunkInput.txt ..\CorInfoBase.cs ..\..\..\crossgen2\jitinterface\jitinterface.h +call ..\..\..\..\..\..\..\dotnet.cmd run -- InstructionSetGenerator InstructionSetDesc.txt ..\..\Internal\Runtime\ReadyToRunInstructionSet.cs ..\CorInfoInstructionSet.cs ..\..\..\..\inc\corinfoinstructionset.h ..\..\..\..\inc\readytoruninstructionset.h +popd \ No newline at end of file diff --git a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.sh b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.sh index 59672c72d4156b..041e410ae98aa1 100755 --- a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.sh +++ b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.sh @@ -1,3 +1,4 @@ #!/usr/bin/env bash cd "$(dirname ${BASH_SOURCE[0]})" -dotnet run -- ThunkInput.txt ../CorInfoBase.cs ../../../crossgen2/jitinterface/jitinterface.h +../../../../../../../dotnet.sh run -- ThunkInput.txt ../CorInfoBase.cs ../../../crossgen2/jitinterface/jitinterface.h +../../../../../../../dotnet.sh run -- InstructionSetGenerator InstructionSetDesc.txt ../../Internal/Runtime/ReadyToRunInstructionSet.cs ../CorInfoInstructionSet.cs ../../../../inc/corinfoinstructionset.h ../../../../inc/readytoruninstructionset.h \ No newline at end of file diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index 9c416513431dd0..a1e95d8a19cdca 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -234,6 +234,9 @@ JitInterface\CorInfoTypes.cs + + JitInterface\CorInfoInstructionSet.cs + JitInterface\JitConfigProvider.cs diff --git a/src/coreclr/src/tools/crossgen2/jitinterface/jitwrapper.cpp b/src/coreclr/src/tools/crossgen2/jitinterface/jitwrapper.cpp index fbc01702767309..621b291cf74c24 100644 --- a/src/coreclr/src/tools/crossgen2/jitinterface/jitwrapper.cpp +++ b/src/coreclr/src/tools/crossgen2/jitinterface/jitwrapper.cpp @@ -27,11 +27,11 @@ class CORJIT_FLAGS uint64_t corJitFlags; }; -static const GUID JITEEVersionIdentifier = { /* c231d2d7-4764-4097-a9ef-5961041540df */ - 0xc231d2d7, - 0x4764, - 0x4097, - {0xa9, 0xef, 0x59, 0x61, 0x04, 0x15, 0x40, 0xdf} +static const GUID JITEEVersionIdentifier = { /* 54305fa1-a0d8-42e4-a6b4-b750a8143467 */ + 0x54305fa1, + 0xa0d8, + 0x42e4, + {0xa6, 0xb4, 0xb7, 0x50, 0xa8, 0x14, 0x34, 0x67} }; class Jit diff --git a/src/coreclr/src/vm/codeman.cpp b/src/coreclr/src/vm/codeman.cpp index 4a548638fed09c..947bcf6eb6431f 100644 --- a/src/coreclr/src/vm/codeman.cpp +++ b/src/coreclr/src/vm/codeman.cpp @@ -1296,11 +1296,6 @@ void EEJitManager::SetCpuInfo() CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_CMOV); CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_FCOMI); } - - if (CPU_X86_USE_SSE2(cpuInfo.dwFeatures)) - { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE2); - } #endif // TARGET_X86 #if defined(TARGET_X86) || defined(TARGET_AMD64) @@ -1372,46 +1367,48 @@ void EEJitManager::SetCpuInfo() if ((buffer[15] & 0x06) == 0x06) // SSE & SSE2 { + CPUCompileFlags.Set(InstructionSet_SSE); + CPUCompileFlags.Set(InstructionSet_SSE2); if ((buffer[11] & 0x02) != 0) // AESNI { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_AES); + CPUCompileFlags.Set(InstructionSet_AES); } if ((buffer[8] & 0x02) != 0) // PCLMULQDQ { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_PCLMULQDQ); + CPUCompileFlags.Set(InstructionSet_PCLMULQDQ); } if ((buffer[8] & 0x01) != 0) // SSE3 { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE3); + CPUCompileFlags.Set(InstructionSet_SSE3); if ((buffer[9] & 0x02) != 0) // SSSE3 { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSSE3); + CPUCompileFlags.Set(InstructionSet_SSSE3); if ((buffer[10] & 0x08) != 0) // SSE4.1 { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE41); + CPUCompileFlags.Set(InstructionSet_SSE41); if ((buffer[10] & 0x10) != 0) // SSE4.2 { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE42); + CPUCompileFlags.Set(InstructionSet_SSE42); if ((buffer[10] & 0x80) != 0) // POPCNT { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_POPCNT); + CPUCompileFlags.Set(InstructionSet_POPCNT); } if ((buffer[11] & 0x18) == 0x18) // AVX & OSXSAVE { if(DoesOSSupportAVX() && (xmmYmmStateSupport() == 1)) { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_AVX); + CPUCompileFlags.Set(InstructionSet_AVX); if ((buffer[9] & 0x10) != 0) // FMA { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_FMA); + CPUCompileFlags.Set(InstructionSet_FMA); } if (maxCpuId >= 0x07) @@ -1420,7 +1417,7 @@ void EEJitManager::SetCpuInfo() if ((buffer[4] & 0x20) != 0) // AVX2 { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_AVX2); + CPUCompileFlags.Set(InstructionSet_AVX2); } } } @@ -1439,7 +1436,7 @@ void EEJitManager::SetCpuInfo() if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_SIMD16ByteOnly) != 0) { - CPUCompileFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_USE_AVX2); + CPUCompileFlags.Clear(InstructionSet_AVX2); } } @@ -1449,14 +1446,16 @@ void EEJitManager::SetCpuInfo() if ((buffer[4] & 0x08) != 0) // BMI1 { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_BMI1); + CPUCompileFlags.Set(InstructionSet_BMI1); } if ((buffer[5] & 0x01) != 0) // BMI2 { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_BMI2); + CPUCompileFlags.Set(InstructionSet_BMI2); } } + + CPUCompileFlags.EnsureValidInstructionSetSupport(); } DWORD maxCpuIdEx = getcpuid(0x80000000, buffer); @@ -1471,7 +1470,7 @@ void EEJitManager::SetCpuInfo() if ((buffer[8] & 0x20) != 0) // LZCNT { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_LZCNT); + CPUCompileFlags.Set(InstructionSet_LZCNT); } } #endif // defined(TARGET_X86) || defined(TARGET_AMD64) @@ -1486,23 +1485,25 @@ void EEJitManager::SetCpuInfo() PAL_GetJitCpuCapabilityFlags(&CPUCompileFlags); #elif defined(HOST_64BIT) // FP and SIMD support are enabled by default - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ADVSIMD); - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP); + CPUCompileFlags.Set(InstructionSet_ArmBase); + CPUCompileFlags.Set(InstructionSet_AdvSimd); // PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE (30) if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)) { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_AES); - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA1); - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA256); + CPUCompileFlags.Set(InstructionSet_Aes); + CPUCompileFlags.Set(InstructionSet_Sha1); + CPUCompileFlags.Set(InstructionSet_Sha256); } // PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE (31) if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE)) { - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_CRC32); + CPUCompileFlags.Set(InstructionSet_Crc32); } #endif // HOST_64BIT #endif // TARGET_ARM64 + CPUCompileFlags.Set64BitInstructionSetVariants(); + m_CPUCompileFlags = CPUCompileFlags; } diff --git a/src/coreclr/src/zap/zapper.cpp b/src/coreclr/src/zap/zapper.cpp index a11f605aa83801..70388bd50018bc 100644 --- a/src/coreclr/src/zap/zapper.cpp +++ b/src/coreclr/src/zap/zapper.cpp @@ -1181,10 +1181,17 @@ void Zapper::InitializeCompilerFlags(CORCOMPILE_VERSION_INFO * pVersionInfo) } // .NET Core requires SSE2. - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE2); - #endif // TARGET_X86 +#if defined(TARGET_X86) || defined(TARGET_AMD64) + m_pOpt->m_compilerFlags.Set(InstructionSet_SSE); + m_pOpt->m_compilerFlags.Set(InstructionSet_SSE2); +#endif +#if defined(TARGET_ARM64) + m_pOpt->m_compilerFlags.Set(InstructionSet_ArmBase); + m_pOpt->m_compilerFlags.Set(InstructionSet_AdvSimd); +#endif + #if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) // If we're crossgenning CoreLib, allow generating non-VEX intrinsics. The generated code might // not actually be supported by the processor at runtime so we compensate for it by @@ -1198,21 +1205,24 @@ void Zapper::InitializeCompilerFlags(CORCOMPILE_VERSION_INFO * pVersionInfo) m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_FEATURE_SIMD); #if defined(TARGET_X86) || defined(TARGET_AMD64) - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_AES); - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_PCLMULQDQ); - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE3); - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSSE3); - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE41); - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE42); - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_POPCNT); + m_pOpt->m_compilerFlags.Set(InstructionSet_SSE); + m_pOpt->m_compilerFlags.Set(InstructionSet_SSE2); + m_pOpt->m_compilerFlags.Set(InstructionSet_AES); + m_pOpt->m_compilerFlags.Set(InstructionSet_PCLMULQDQ); + m_pOpt->m_compilerFlags.Set(InstructionSet_SSE3); + m_pOpt->m_compilerFlags.Set(InstructionSet_SSSE3); + m_pOpt->m_compilerFlags.Set(InstructionSet_SSE41); + m_pOpt->m_compilerFlags.Set(InstructionSet_SSE42); + m_pOpt->m_compilerFlags.Set(InstructionSet_POPCNT); // Leaving out CORJIT_FLAGS::CORJIT_FLAG_USE_AVX, CORJIT_FLAGS::CORJIT_FLAG_USE_FMA // CORJIT_FLAGS::CORJIT_FLAG_USE_AVX2, CORJIT_FLAGS::CORJIT_FLAG_USE_BMI1, // CORJIT_FLAGS::CORJIT_FLAG_USE_BMI2 on purpose - these require VEX encodings // and the JIT doesn't support generating code for methods with mixed encodings. - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_LZCNT); + m_pOpt->m_compilerFlags.Set(InstructionSet_LZCNT); #endif // defined(TARGET_X86) || defined(TARGET_AMD64) } #endif // defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) + m_pOpt->m_compilerFlags.Set64BitInstructionSetVariants(); if ( m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO) && m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE) From b5b96ccc690a69f2bf418aada10295c5ac58f857 Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Sun, 22 Mar 2020 14:31:35 -0700 Subject: [PATCH 2/3] Ensure that 64 bit variants of instruction sets are handled correctly - Make sure to enable them based on the related 32bit instruction sets before disabling instruction sets that are enabled but not compatible with the instruction set hierarchy the runtime is designed for. --- src/coreclr/src/pal/src/misc/jitsupport.cpp | 1 + src/coreclr/src/vm/codeman.cpp | 3 +-- src/coreclr/src/zap/zapper.cpp | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/coreclr/src/pal/src/misc/jitsupport.cpp b/src/coreclr/src/pal/src/misc/jitsupport.cpp index 70123f8d18faaf..72699e0de0f378 100644 --- a/src/coreclr/src/pal/src/misc/jitsupport.cpp +++ b/src/coreclr/src/pal/src/misc/jitsupport.cpp @@ -126,4 +126,5 @@ PAL_GetJitCpuCapabilityFlags(CORJIT_FLAGS *flags) #endif // HAVE_AUXV_HWCAP_H #endif // defined(HOST_ARM64) CPUCompileFlags.Set64BitInstructionSetVariants(); + CPUCompileFlags.EnsureValidInstructionSetSupport(); } diff --git a/src/coreclr/src/vm/codeman.cpp b/src/coreclr/src/vm/codeman.cpp index 947bcf6eb6431f..863b54a240f747 100644 --- a/src/coreclr/src/vm/codeman.cpp +++ b/src/coreclr/src/vm/codeman.cpp @@ -1454,8 +1454,6 @@ void EEJitManager::SetCpuInfo() CPUCompileFlags.Set(InstructionSet_BMI2); } } - - CPUCompileFlags.EnsureValidInstructionSetSupport(); } DWORD maxCpuIdEx = getcpuid(0x80000000, buffer); @@ -1503,6 +1501,7 @@ void EEJitManager::SetCpuInfo() #endif // TARGET_ARM64 CPUCompileFlags.Set64BitInstructionSetVariants(); + CPUCompileFlags.EnsureValidInstructionSetSupport(); m_CPUCompileFlags = CPUCompileFlags; } diff --git a/src/coreclr/src/zap/zapper.cpp b/src/coreclr/src/zap/zapper.cpp index 70388bd50018bc..422775a349257f 100644 --- a/src/coreclr/src/zap/zapper.cpp +++ b/src/coreclr/src/zap/zapper.cpp @@ -1223,6 +1223,7 @@ void Zapper::InitializeCompilerFlags(CORCOMPILE_VERSION_INFO * pVersionInfo) } #endif // defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) m_pOpt->m_compilerFlags.Set64BitInstructionSetVariants(); + m_pOpt->m_compilerFlags.EnsureValidInstructionSetSupport(); if ( m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO) && m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE) From 6eeb8196a594b90cdfd96e4e19a2c0f15f00eb26 Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Sun, 22 Mar 2020 14:36:34 -0700 Subject: [PATCH 3/3] Update jit EE version interface as this revert changes the interface back to the pre-revert state. --- src/coreclr/src/inc/corinfo.h | 10 +++++----- .../src/tools/crossgen2/jitinterface/jitwrapper.cpp | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/coreclr/src/inc/corinfo.h b/src/coreclr/src/inc/corinfo.h index 741b12e4f3afd6..9f69ac206d7b1d 100644 --- a/src/coreclr/src/inc/corinfo.h +++ b/src/coreclr/src/inc/corinfo.h @@ -217,11 +217,11 @@ TODO: Talk about initializing strutures before use #endif #endif -SELECTANY const GUID JITEEVersionIdentifier = { /* 54305fa1-a0d8-42e4-a6b4-b750a8143467 */ - 0x54305fa1, - 0xa0d8, - 0x42e4, - {0xa6, 0xb4, 0xb7, 0x50, 0xa8, 0x14, 0x34, 0x67} +SELECTANY const GUID JITEEVersionIdentifier = { /* 2296da7b-3823-4d8a-8a6d-b7d4481d41e0 */ + 0x2296da7b, + 0x3823, + 0x4d8a, + {0x8a, 0x6d, 0xb7, 0xd4, 0x48, 0x1d, 0x41, 0xe0} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/src/tools/crossgen2/jitinterface/jitwrapper.cpp b/src/coreclr/src/tools/crossgen2/jitinterface/jitwrapper.cpp index 621b291cf74c24..6151882c8fa5fc 100644 --- a/src/coreclr/src/tools/crossgen2/jitinterface/jitwrapper.cpp +++ b/src/coreclr/src/tools/crossgen2/jitinterface/jitwrapper.cpp @@ -27,11 +27,11 @@ class CORJIT_FLAGS uint64_t corJitFlags; }; -static const GUID JITEEVersionIdentifier = { /* 54305fa1-a0d8-42e4-a6b4-b750a8143467 */ - 0x54305fa1, - 0xa0d8, - 0x42e4, - {0xa6, 0xb4, 0xb7, 0x50, 0xa8, 0x14, 0x34, 0x67} +static const GUID JITEEVersionIdentifier = { /* 2296da7b-3823-4d8a-8a6d-b7d4481d41e0 */ + 0x2296da7b, + 0x3823, + 0x4d8a, + {0x8a, 0x6d, 0xb7, 0xd4, 0x48, 0x1d, 0x41, 0xe0} }; class Jit