From f80a5147ef7662c3238275568c9dad7655a9684f Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Thu, 19 Mar 2020 09:29:19 -0700 Subject: [PATCH] Unify instruction set definition (#33730) * Unify instruction set definition - Build simple DSL to describe the instruction set support of the compiler/jit/etc - Parse DSL and produce data structures useable throughout our compilation environment - This is in support of adding more granular instruction set support to crossgen2, but this change is pulled out into its own PR to ease reviewing cost - Make it hard to mess up 64bit instruction set variants by adding helper function to fill them in. - Add 64 bit variant names to 32bit instruction set enum to remove the need to add a large number of #ifdefs to the jit --- .../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 c4a9f4745cd13..21c104b63db22 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 9978fac982c5c..741b12e4f3afd 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 0000000000000..d43d743134f44 --- /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 18f24b52acdfb..eac6f9277909d 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 0000000000000..6e6f2549f9044 --- /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 6febed12de9fd..0d4fc4a704dc2 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 2a87d9c232686..9afa3feca1997 100644 --- a/src/coreclr/src/jit/compiler.h +++ b/src/coreclr/src/jit/compiler.h @@ -3672,7 +3672,7 @@ class Compiler bool mustExpand); protected: - bool compSupportsHWIntrinsic(InstructionSet isa); + bool compSupportsHWIntrinsic(CORINFO_InstructionSet isa); GenTree* impSpecialIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, @@ -8270,7 +8270,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; @@ -8379,11 +8379,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 4ac4c24dfde05..78d3d8e59274a 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 4b8848bbf458c..4af653b766e6b 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 2931c51813e1e..b80dce7f1c0b0 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 1f7dde990cc7d..7f494ab96582f 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 1ba67be0bb2d9..cb5160e5cb937 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 6aa59aa2bb7f6..80b341f1c90ec 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 0de79a4cc1387..26ba6eec4ac01 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 473bfc58ff123..405ef9a7d7421 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 6a695a1185a0a..b9de46de1910b 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 19c914e614d91..2578cd7fbdc92 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 d49fa6008451d..8ca69e35be37a 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 0da36ab8903a6..70123f8d18faa 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 0000000000000..aff37abdf06ac --- /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 1fadcd5cda5f1..5dfeee4a7676e 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 0000000000000..470faeb0713ba --- /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 1647c4fb75da5..64d4a0649dfa0 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 0000000000000..9c8404fe8969f --- /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 0000000000000..3d5ea118732e3 --- /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 78b513211cc4a..94fa40662716d 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 46328b52d08ba..f90ce4554e37a 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 59672c72d4156..041e410ae98aa 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 9c416513431dd..a1e95d8a19cdc 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 fbc0170276730..621b291cf74c2 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 5b3fcb818b001..9b3a2764bf636 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 a11f605aa8380..70388bd50018b 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)