1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
9 enum class SupportedISA
12 AVX2 = 1 << (int)InstructionSet::AVX2,
13 AVX512F = 1 << (int)InstructionSet::AVX512F
16 #if defined(TARGET_AMD64) && defined(TARGET_WINDOWS)
18 static DWORD64 GetEnabledXStateFeaturesHelper()
20 LIMITED_METHOD_CONTRACT;
22 // On Windows we have an api(GetEnabledXStateFeatures) to check if AVX is supported
23 typedef DWORD64(WINAPI* PGETENABLEDXSTATEFEATURES)();
24 PGETENABLEDXSTATEFEATURES pfnGetEnabledXStateFeatures = NULL;
26 HMODULE hMod = WszLoadLibraryEx(WINDOWS_KERNEL32_DLLNAME_W, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
30 pfnGetEnabledXStateFeatures = (PGETENABLEDXSTATEFEATURES)GetProcAddress(hMod, "GetEnabledXStateFeatures");
32 if (pfnGetEnabledXStateFeatures == NULL)
37 DWORD64 FeatureMask = pfnGetEnabledXStateFeatures();
42 SupportedISA DetermineSupportedISA()
44 // register definitions to make the following code more readable
54 // bit definitions to make code more readable
66 return SupportedISA::None;
70 // both AVX and OCXSAVE feature flags must be enabled
71 if ((reg[ECX] & (OCXSAVE|AVX)) != (OCXSAVE | AVX))
72 return SupportedISA::None;
75 DWORD64 xcr0 = _xgetbv(0);
78 DWORD64 FeatureMask = GetEnabledXStateFeaturesHelper();
80 // get processor extended feature flag info
83 // check if both AVX2 and AVX512F are supported by both processor and OS
84 if ((reg[EBX] & (AVX2 | AVX512F)) == (AVX2 | AVX512F) &&
85 (xcr0 & 0xe6) == 0xe6 &&
86 (FeatureMask & (XSTATE_MASK_AVX | XSTATE_MASK_AVX512)) == (XSTATE_MASK_AVX | XSTATE_MASK_AVX512))
88 return (SupportedISA)((int)SupportedISA::AVX2 | (int)SupportedISA::AVX512F);
91 // check if AVX2 is supported by both processor and OS
92 if ((reg[EBX] & AVX2) &&
93 (xcr0 & 0x06) == 0x06 &&
94 (FeatureMask & XSTATE_MASK_AVX) == XSTATE_MASK_AVX)
96 return SupportedISA::AVX2;
99 return SupportedISA::None;
102 #elif defined(TARGET_UNIX)
104 SupportedISA DetermineSupportedISA()
106 __builtin_cpu_init();
107 if (__builtin_cpu_supports("avx2"))
109 if (__builtin_cpu_supports("avx512f"))
110 return (SupportedISA)((int)SupportedISA::AVX2 | (int)SupportedISA::AVX512F);
112 return SupportedISA::AVX2;
116 return SupportedISA::None;
120 #endif // defined(TARGET_UNIX)
122 static bool s_initialized;
123 static SupportedISA s_supportedISA;
125 bool IsSupportedInstructionSet (InstructionSet instructionSet)
127 assert(s_initialized);
128 assert(instructionSet == InstructionSet::AVX2 || instructionSet == InstructionSet::AVX512F);
129 return ((int)s_supportedISA & (1 << (int)instructionSet)) != 0;
132 void InitSupportedInstructionSet (int32_t configSetting)
134 s_supportedISA = (SupportedISA)((int)DetermineSupportedISA() & configSetting);
135 // we are assuming that AVX2 can be used if AVX512F can,
136 // so if AVX2 is disabled, we need to disable AVX512F as well
137 if (!((int)s_supportedISA & (int)SupportedISA::AVX2))
138 s_supportedISA = SupportedISA::None;
139 s_initialized = true;