Merge #13471: For AVX2 code, also check for AVX, XSAVE, and OS support

32d153fa36 For AVX2 code, also check for AVX, XSAVE, and OS support (Pieter Wuille)

Pull request description:

  Fixes #12903.

Tree-SHA512: 01e71efb5d3a43c49a145a5b1dc4fe7d0a491e1e78479e7df830a2aaac57c3dcfc316e28984c695206c76f93b68e4350fc037ca36756ca579b7070e39c835da2
This commit is contained in:
Wladimir J. van der Laan 2018-06-24 15:30:07 +02:00
commit 5eca4e86d4
No known key found for this signature in database
GPG key ID: 1E4AED62986CD25D

View file

@ -536,6 +536,14 @@ void inline cpuid(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uin
{ {
__asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf)); __asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf));
} }
/** Check whether the OS has enabled AVX registers. */
bool AVXEnabled()
{
uint32_t a, d;
__asm__("xgetbv" : "=a"(a), "=d"(d) : "c"(0));
return (a & 6) == 6;
}
#endif #endif
} // namespace } // namespace
@ -544,6 +552,7 @@ std::string SHA256AutoDetect()
{ {
std::string ret = "standard"; std::string ret = "standard";
#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__) || defined(__i386__)) #if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__) || defined(__i386__))
(void)AVXEnabled; // Silence unused warning (in case ENABLE_AVX2 is not defined)
uint32_t eax, ebx, ecx, edx; uint32_t eax, ebx, ecx, edx;
cpuid(1, 0, eax, ebx, ecx, edx); cpuid(1, 0, eax, ebx, ecx, edx);
if ((ecx >> 19) & 1) { if ((ecx >> 19) & 1) {
@ -555,11 +564,15 @@ std::string SHA256AutoDetect()
TransformD64_4way = sha256d64_sse41::Transform_4way; TransformD64_4way = sha256d64_sse41::Transform_4way;
ret = "sse4(1way+4way)"; ret = "sse4(1way+4way)";
#if defined(ENABLE_AVX2) && !defined(BUILD_BITCOIN_INTERNAL) #if defined(ENABLE_AVX2) && !defined(BUILD_BITCOIN_INTERNAL)
if (((ecx >> 27) & 1) && ((ecx >> 28) & 1)) { // XSAVE and AVX
cpuid(7, 0, eax, ebx, ecx, edx); cpuid(7, 0, eax, ebx, ecx, edx);
if ((ebx >> 5) & 1) { if ((ebx >> 5) & 1) { // AVX2 flag
if (AVXEnabled()) { // OS has enabled AVX registers
TransformD64_8way = sha256d64_avx2::Transform_8way; TransformD64_8way = sha256d64_avx2::Transform_8way;
ret += ",avx2(8way)"; ret += ",avx2(8way)";
} }
}
}
#endif #endif
#else #else
ret = "sse4"; ret = "sse4";