From: Steve MacLean Date: Wed, 13 Dec 2017 12:00:28 +0000 (-0500) Subject: [Arm64/Linux] PAL_GetJitCpuCapabilityFlags() (#15447) X-Git-Tag: accepted/tizen/base/20180629.140029~340 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9f1dc4444478ccbac2476d53949c471583876ad7;p=platform%2Fupstream%2Fcoreclr.git [Arm64/Linux] PAL_GetJitCpuCapabilityFlags() (#15447) Initial PAL API definition Implementation for ARM64/Linux --- diff --git a/src/inc/corjit.h b/src/inc/corjit.h index 91cfb26..cadfdff 100644 --- a/src/inc/corjit.h +++ b/src/inc/corjit.h @@ -32,6 +32,8 @@ #include +#include + #define CORINFO_STACKPROBE_DEPTH 256*sizeof(UINT_PTR) // Guaranteed stack until an fcall/unmanaged // code can set up a frame. Please make sure // this is less than a page. This is due to @@ -72,236 +74,6 @@ enum CorJitResult CORJIT_RECOVERABLEERROR = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 5), }; -class CORJIT_FLAGS -{ -public: - - enum CorJitFlag - { - CORJIT_FLAG_CALL_GETJITFLAGS = 0xffffffff, // Indicates that the JIT should retrieve flags in the form of a - // pointer to a CORJIT_FLAGS value via ICorJitInfo::getJitFlags(). - CORJIT_FLAG_SPEED_OPT = 0, - CORJIT_FLAG_SIZE_OPT = 1, - CORJIT_FLAG_DEBUG_CODE = 2, // generate "debuggable" code (no code-mangling optimizations) - CORJIT_FLAG_DEBUG_EnC = 3, // We are in Edit-n-Continue mode - CORJIT_FLAG_DEBUG_INFO = 4, // generate line and local-var info - CORJIT_FLAG_MIN_OPT = 5, // disable all jit optimizations (not necesarily debuggable code) - CORJIT_FLAG_GCPOLL_CALLS = 6, // Emit calls to JIT_POLLGC for thread suspension. - CORJIT_FLAG_MCJIT_BACKGROUND = 7, // Calling from multicore JIT background thread, do not call JitComplete - - #if defined(_TARGET_X86_) - - CORJIT_FLAG_PINVOKE_RESTORE_ESP = 8, // Restore ESP after returning from inlined PInvoke - 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_) - - CORJIT_FLAG_UNUSED1 = 8, - CORJIT_FLAG_UNUSED2 = 9, - CORJIT_FLAG_UNUSED3 = 10, - CORJIT_FLAG_UNUSED4 = 11, - CORJIT_FLAG_UNUSED5 = 12, - - #endif // !defined(_TARGET_X86_) - - #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) - - CORJIT_FLAG_USE_SSE3_4 = 13, - 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_UNUSED6 = 13, - 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, - #else - CORJIT_FLAG_UNUSED10 = 17, - #endif // !(defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)) - - CORJIT_FLAG_MAKEFINALCODE = 18, // Use the final code generator, i.e., not the interpreter. - CORJIT_FLAG_READYTORUN = 19, // Use version-resilient code generation - CORJIT_FLAG_PROF_ENTERLEAVE = 20, // Instrument prologues/epilogues - CORJIT_FLAG_PROF_REJIT_NOPS = 21, // Insert NOPs to ensure code is re-jitable - CORJIT_FLAG_PROF_NO_PINVOKE_INLINE = 22, // Disables PInvoke inlining - CORJIT_FLAG_SKIP_VERIFICATION = 23, // (lazy) skip verification - determined without doing a full resolve. See comment below - CORJIT_FLAG_PREJIT = 24, // jit or prejit is the execution engine. - CORJIT_FLAG_RELOC = 25, // Generate relocatable code - CORJIT_FLAG_IMPORT_ONLY = 26, // Only import the function - CORJIT_FLAG_IL_STUB = 27, // method is an IL stub - CORJIT_FLAG_PROCSPLIT = 28, // JIT should separate code into hot and cold sections - CORJIT_FLAG_BBINSTR = 29, // Collect basic block profile information - CORJIT_FLAG_BBOPT = 30, // Optimize method based on profile information - CORJIT_FLAG_FRAMED = 31, // All methods have an EBP frame - CORJIT_FLAG_ALIGN_LOOPS = 32, // add NOPs before loops to align them at 16 byte boundaries - CORJIT_FLAG_PUBLISH_SECRET_PARAM = 33, // JIT must place stub secret param into local 0. (used by IL stubs) - CORJIT_FLAG_GCPOLL_INLINE = 34, // JIT must inline calls to GCPoll when possible - CORJIT_FLAG_SAMPLING_JIT_BACKGROUND = 35, // JIT is being invoked as a result of stack sampling for hot methods in the background - CORJIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions - CORJIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog - CORJIT_FLAG_DESKTOP_QUIRKS = 38, // The JIT should generate desktop-quirk-compatible code - CORJIT_FLAG_TIER0 = 39, // This is the initial tier for tiered compilation which should generate code as quickly as possible - CORJIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code - -#if defined(_TARGET_ARM_) - CORJIT_FLAG_RELATIVE_CODE_RELOCS = 41, // JIT should generate PC-relative address computations instead of EE relocation records -#else // !defined(_TARGET_ARM_) - CORJIT_FLAG_UNUSED11 = 41, -#endif // !defined(_TARGET_ARM_) - - 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_SHA2 = 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 - -#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, - CORJIT_FLAG_UNUSED15 = 46, - CORJIT_FLAG_UNUSED16 = 47, - CORJIT_FLAG_UNUSED17 = 48, - CORJIT_FLAG_UNUSED18 = 49, - CORJIT_FLAG_UNUSED19 = 50, - CORJIT_FLAG_UNUSED20 = 51, - CORJIT_FLAG_UNUSED21 = 52, - CORJIT_FLAG_UNUSED22 = 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 - -#endif // !defined(_TARGET_ARM64_) && !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) - }; - - CORJIT_FLAGS() - : corJitFlags(0) - { - // empty - } - - // Convenience constructor to set exactly one flag. - CORJIT_FLAGS(CorJitFlag flag) - : corJitFlags(0) - { - Set(flag); - } - - CORJIT_FLAGS(const CORJIT_FLAGS& other) - { - corJitFlags = other.corJitFlags; - } - - void Reset() - { - corJitFlags = 0; - } - - void Set(CorJitFlag flag) - { - corJitFlags |= 1ULL << (unsigned __int64)flag; - } - - void Clear(CorJitFlag flag) - { - corJitFlags &= ~(1ULL << (unsigned __int64)flag); - } - - bool IsSet(CorJitFlag flag) const - { - return (corJitFlags & (1ULL << (unsigned __int64)flag)) != 0; - } - - void Add(const CORJIT_FLAGS& other) - { - corJitFlags |= other.corJitFlags; - } - - void Remove(const CORJIT_FLAGS& other) - { - corJitFlags &= ~other.corJitFlags; - } - - bool IsEmpty() const - { - return corJitFlags == 0; - } - - // DO NOT USE THIS FUNCTION! (except in very restricted special cases) - unsigned __int64 GetFlagsRaw() - { - return corJitFlags; - } - -private: - - unsigned __int64 corJitFlags; -}; - - /***************************************************************************** Here is how CORJIT_FLAG_SKIP_VERIFICATION should be interepreted. Note that even if any method is inlined, it need not be verified. diff --git a/src/inc/corjitflags.h b/src/inc/corjitflags.h new file mode 100644 index 0000000..2598c26 --- /dev/null +++ b/src/inc/corjitflags.h @@ -0,0 +1,250 @@ +// 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. + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +// +// The JIT/EE interface is versioned. By "interface", we mean mean any and all communication between the +// JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier +// must be updated. See code:JITEEVersionIdentifier for more information. +// +// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +// +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef _COR_JIT_FLAGS_H_ +#define _COR_JIT_FLAGS_H_ + +class CORJIT_FLAGS +{ +public: + + enum CorJitFlag + { + CORJIT_FLAG_CALL_GETJITFLAGS = 0xffffffff, // Indicates that the JIT should retrieve flags in the form of a + // pointer to a CORJIT_FLAGS value via ICorJitInfo::getJitFlags(). + CORJIT_FLAG_SPEED_OPT = 0, + CORJIT_FLAG_SIZE_OPT = 1, + CORJIT_FLAG_DEBUG_CODE = 2, // generate "debuggable" code (no code-mangling optimizations) + CORJIT_FLAG_DEBUG_EnC = 3, // We are in Edit-n-Continue mode + CORJIT_FLAG_DEBUG_INFO = 4, // generate line and local-var info + CORJIT_FLAG_MIN_OPT = 5, // disable all jit optimizations (not necesarily debuggable code) + CORJIT_FLAG_GCPOLL_CALLS = 6, // Emit calls to JIT_POLLGC for thread suspension. + CORJIT_FLAG_MCJIT_BACKGROUND = 7, // Calling from multicore JIT background thread, do not call JitComplete + + #if defined(_TARGET_X86_) + + CORJIT_FLAG_PINVOKE_RESTORE_ESP = 8, // Restore ESP after returning from inlined PInvoke + 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_) + + CORJIT_FLAG_UNUSED1 = 8, + CORJIT_FLAG_UNUSED2 = 9, + CORJIT_FLAG_UNUSED3 = 10, + CORJIT_FLAG_UNUSED4 = 11, + CORJIT_FLAG_UNUSED5 = 12, + + #endif // !defined(_TARGET_X86_) + + #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) + + CORJIT_FLAG_USE_SSE3_4 = 13, + 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_UNUSED6 = 13, + 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, + #else + CORJIT_FLAG_UNUSED10 = 17, + #endif // !(defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)) + + CORJIT_FLAG_MAKEFINALCODE = 18, // Use the final code generator, i.e., not the interpreter. + CORJIT_FLAG_READYTORUN = 19, // Use version-resilient code generation + CORJIT_FLAG_PROF_ENTERLEAVE = 20, // Instrument prologues/epilogues + CORJIT_FLAG_PROF_REJIT_NOPS = 21, // Insert NOPs to ensure code is re-jitable + CORJIT_FLAG_PROF_NO_PINVOKE_INLINE = 22, // Disables PInvoke inlining + CORJIT_FLAG_SKIP_VERIFICATION = 23, // (lazy) skip verification - determined without doing a full resolve. See comment below + CORJIT_FLAG_PREJIT = 24, // jit or prejit is the execution engine. + CORJIT_FLAG_RELOC = 25, // Generate relocatable code + CORJIT_FLAG_IMPORT_ONLY = 26, // Only import the function + CORJIT_FLAG_IL_STUB = 27, // method is an IL stub + CORJIT_FLAG_PROCSPLIT = 28, // JIT should separate code into hot and cold sections + CORJIT_FLAG_BBINSTR = 29, // Collect basic block profile information + CORJIT_FLAG_BBOPT = 30, // Optimize method based on profile information + CORJIT_FLAG_FRAMED = 31, // All methods have an EBP frame + CORJIT_FLAG_ALIGN_LOOPS = 32, // add NOPs before loops to align them at 16 byte boundaries + CORJIT_FLAG_PUBLISH_SECRET_PARAM = 33, // JIT must place stub secret param into local 0. (used by IL stubs) + CORJIT_FLAG_GCPOLL_INLINE = 34, // JIT must inline calls to GCPoll when possible + CORJIT_FLAG_SAMPLING_JIT_BACKGROUND = 35, // JIT is being invoked as a result of stack sampling for hot methods in the background + CORJIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions + CORJIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog + CORJIT_FLAG_DESKTOP_QUIRKS = 38, // The JIT should generate desktop-quirk-compatible code + CORJIT_FLAG_TIER0 = 39, // This is the initial tier for tiered compilation which should generate code as quickly as possible + CORJIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code + +#if defined(_TARGET_ARM_) + CORJIT_FLAG_RELATIVE_CODE_RELOCS = 41, // JIT should generate PC-relative address computations instead of EE relocation records +#else // !defined(_TARGET_ARM_) + CORJIT_FLAG_UNUSED11 = 41, +#endif // !defined(_TARGET_ARM_) + + 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_SHA2 = 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 + +#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, + CORJIT_FLAG_UNUSED15 = 46, + CORJIT_FLAG_UNUSED16 = 47, + CORJIT_FLAG_UNUSED17 = 48, + CORJIT_FLAG_UNUSED18 = 49, + CORJIT_FLAG_UNUSED19 = 50, + CORJIT_FLAG_UNUSED20 = 51, + CORJIT_FLAG_UNUSED21 = 52, + CORJIT_FLAG_UNUSED22 = 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 + +#endif // !defined(_TARGET_ARM64_) &&!defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) + }; + + CORJIT_FLAGS() + : corJitFlags(0) + { + // empty + } + + // Convenience constructor to set exactly one flag. + CORJIT_FLAGS(CorJitFlag flag) + : corJitFlags(0) + { + Set(flag); + } + + CORJIT_FLAGS(const CORJIT_FLAGS& other) + { + corJitFlags = other.corJitFlags; + } + + void Reset() + { + corJitFlags = 0; + } + + void Set(CorJitFlag flag) + { + corJitFlags |= 1ULL << (unsigned __int64)flag; + } + + void Clear(CorJitFlag flag) + { + corJitFlags &= ~(1ULL << (unsigned __int64)flag); + } + + bool IsSet(CorJitFlag flag) const + { + return (corJitFlags & (1ULL << (unsigned __int64)flag)) != 0; + } + + void Add(const CORJIT_FLAGS& other) + { + corJitFlags |= other.corJitFlags; + } + + void Remove(const CORJIT_FLAGS& other) + { + corJitFlags &= ~other.corJitFlags; + } + + bool IsEmpty() const + { + return corJitFlags == 0; + } + + // DO NOT USE THIS FUNCTION! (except in very restricted special cases) + unsigned __int64 GetFlagsRaw() + { + return corJitFlags; + } + +private: + + unsigned __int64 corJitFlags; +}; + + +#endif // _COR_JIT_FLAGS_H_ diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index e8fdab5..0e085bd 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -5453,6 +5453,19 @@ unsigned int _mm_getcsr(void); PALIMPORT void _mm_setcsr(unsigned int i); +/******************* PAL functions for CPU capability detection *******/ + +#ifdef __cplusplus + +class CORJIT_FLAGS; + +PALIMPORT +VOID +PALAPI +PAL_GetJitCpuCapabilityFlags(CORJIT_FLAGS *flags); + +#endif + /******************* PAL side-by-side support ************************/ #ifdef FEATURE_PAL_SXS diff --git a/src/pal/src/CMakeLists.txt b/src/pal/src/CMakeLists.txt index 3bfc348..2ade61b 100644 --- a/src/pal/src/CMakeLists.txt +++ b/src/pal/src/CMakeLists.txt @@ -174,6 +174,7 @@ set(SOURCES misc/error.cpp misc/errorstrings.cpp misc/fmtmessage.cpp + misc/jitsupport.cpp misc/miscpalapi.cpp misc/msgbox.cpp misc/strutil.cpp diff --git a/src/pal/src/config.h.in b/src/pal/src/config.h.in index 0052880..7968192 100644 --- a/src/pal/src/config.h.in +++ b/src/pal/src/config.h.in @@ -23,6 +23,7 @@ #cmakedefine01 HAVE_PRCTL_H #cmakedefine01 HAVE_NUMA_H #cmakedefine01 HAVE_PTHREAD_NP_H +#cmakedefine01 HAVE_AUXV_HWCAP_H #cmakedefine01 HAVE_KQUEUE #cmakedefine01 HAVE_PTHREAD_SUSPEND diff --git a/src/pal/src/configure.cmake b/src/pal/src/configure.cmake index b797caf..86b5d94 100644 --- a/src/pal/src/configure.cmake +++ b/src/pal/src/configure.cmake @@ -37,6 +37,7 @@ check_include_files(semaphore.h HAVE_SEMAPHORE_H) check_include_files(sys/prctl.h HAVE_PRCTL_H) check_include_files(numa.h HAVE_NUMA_H) check_include_files(pthread_np.h HAVE_PTHREAD_NP_H) +check_include_files("sys/auxv.h;asm/hwcap.h" HAVE_AUXV_HWCAP_H) if(NOT CMAKE_SYSTEM_NAME STREQUAL FreeBSD AND NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD) set(CMAKE_REQUIRED_FLAGS "-ldl") diff --git a/src/pal/src/misc/jitsupport.cpp b/src/pal/src/misc/jitsupport.cpp new file mode 100644 index 0000000..917319d --- /dev/null +++ b/src/pal/src/misc/jitsupport.cpp @@ -0,0 +1,132 @@ +// 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. + + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(MISC); + +#if defined(_ARM64_) +#define _TARGET_ARM64_ +#endif + +#include "../../../inc/corjitflags.h" + +#if HAVE_AUXV_HWCAP_H +#include +#include +#endif + +PALIMPORT +VOID +PALAPI +PAL_GetJitCpuCapabilityFlags(CORJIT_FLAGS *flags) +{ + _ASSERTE(flags); + +#if defined(_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. +// From a single binary distribution perspective, compiling with latest kernel asm/hwcap.h should +// include all published flags. Given flags are merged to kernel and published before silicon is +// 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); +#endif +#ifdef HWCAP_ATOMICS + if (hwCap & HWCAP_ATOMICS) + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ATOMICS); +#endif +#ifdef HWCAP_CRC32 + if (hwCap & HWCAP_CRC32) + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_CRC32); +#endif +#ifdef HWCAP_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); +#endif +#ifdef HWCAP_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); +#endif +#ifdef HWCAP_FPHP + 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); +#endif +#ifdef HWCAP_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); +#endif +#ifdef HWCAP_SHA1 + if (hwCap & HWCAP_SHA1) + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA1); +#endif +#ifdef HWCAP_SHA2 + if (hwCap & HWCAP_SHA2) + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA2); +#endif +#ifdef HWCAP_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); +#endif +#ifdef HWCAP_ASIMD + if (hwCap & HWCAP_ASIMD) + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SIMD); +#endif +#ifdef HWCAP_ASIMDRDM + if (hwCap & HWCAP_ASIMDRDM) + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SIMD_V81); +#endif +#ifdef HWCAP_ASIMDHP + if (hwCap & HWCAP_ASIMDHP) + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SIMD_FP16); +#endif +#ifdef HWCAP_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); +#endif +#ifdef HWCAP_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_SIMD); + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP); +#endif // HAVE_AUXV_HWCAP_H +#endif // defined(_ARM64_) +} diff --git a/src/vm/codeman.cpp b/src/vm/codeman.cpp index 67ac185..b1e6746 100644 --- a/src/vm/codeman.cpp +++ b/src/vm/codeman.cpp @@ -1441,6 +1441,10 @@ void EEJitManager::SetCpuInfo() } #endif // defined(_TARGET_X86_) || defined(_TARGET_AMD64_) +#if defined(_TARGET_ARM64_) && defined(FEATURE_PAL) + PAL_GetJitCpuCapabilityFlags(&CPUCompileFlags); +#endif + #if defined(_TARGET_ARM64_) static ConfigDWORD fFeatureSIMD; if (fFeatureSIMD.val(CLRConfig::EXTERNAL_FeatureSIMD) != 0)