fix: Add `x86_64` archspec support for Windows (#3803)

Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Co-authored-by: Johan Mabille <johan.mabille@gmail.com>
This commit is contained in:
Julien Jerphanion 2025-02-24 12:25:39 +01:00 committed by GitHub
parent 6227622587
commit cdcec32230
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 67 additions and 0 deletions

View File

@ -236,6 +236,73 @@ namespace mamba
{
return "x86_64_v2";
}
#elif defined(_MSC_VER) && defined(_M_X64)
// We apply boolean masks to the results of the cpuid instruction
// to determine if the CPU supports the required instruction sets.
// The masks are generated by shifting 1 to the left by the bit
// position of the required feature.
//
// See those sources to understand bitshifts:
// https://docs.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex?view=msvc-160
// https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels
int cpu_info[4];
int eax_value = 0;
// Check the value of the leaf to determine if the CPU exposes the bit for
// the extended features.
__cpuid(cpu_info, eax_value);
int max_leaf = cpu_info[0];
// Get the extended features for `x86_64_v4` and some of `x86_64_v3`.
// See column "EBX" of table "CPUID EAX=7,ECX=0: Extended feature bits in EBX, ECX and
// EDX": https://en.wikipedia.org/wiki/CPUID#EAX=7,_ECX=0:_Extended_Features
int ecx_value = 0;
eax_value = 7;
__cpuidex(cpu_info, eax_value, ecx_value);
int ebx_value = cpu_info[1];
if (max_leaf >= 7)
{
bool avx512f = ebx_value & (1 << 16);
bool avx512dq = ebx_value & (1 << 17);
bool avx512cd = ebx_value & (1 << 28);
bool avx512bw = ebx_value & (1 << 30);
bool avx512vl = ebx_value & (1 << 31);
if (avx512f && avx512dq && avx512cd && avx512bw && avx512vl)
{
return "x86_64_v4";
}
}
bool bmi1 = ebx_value & (1 << 3);
bool avx2 = ebx_value & (1 << 5);
bool bmi2 = ebx_value & (1 << 8);
// Get the remaining extended features of `x86_64_v3` and all of `x86_64_v2`.
// See second "ECX" column of table "CPUID EAX=1: Feature Information in EDX and ECX":
// https://en.wikipedia.org/wiki/CPUID#EAX=1:_Processor_Info_and_Feature_Bits
eax_value = 1;
ecx_value = 0;
__cpuidex(cpu_info, eax_value, ecx_value);
ecx_value = cpu_info[2];
bool fma_ = ecx_value & (1 << 12);
bool avx = ecx_value & (1 << 28);
if (bmi1 && avx2 && bmi2 && fma_ && avx)
{
return "x86_64_v3";
}
bool sse3 = ecx_value & (1 << 0);
bool ssse3 = ecx_value & (1 << 9);
bool sse4_1 = ecx_value & (1 << 19);
bool sse4_2 = ecx_value & (1 << 20);
bool popcnt = ecx_value & (1 << 23);
if (sse3 && ssse3 && sse4_1 && sse4_2 && popcnt)
{
return "x86_64_v2";
}
#endif
return "x86_64";
}