diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-06-24 15:30:07 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-06-24 15:31:33 +0200 |
commit | 5eca4e86d4ef3b50605c38eacbba53872749de3c (patch) | |
tree | a494a3c3bf9788ab5eadbf0207bbc49c7ee875ab | |
parent | 3a4549301ab2468cd9ae0865aa66819878ae409a (diff) | |
parent | 32d153fa360f73b4999701b97d55b12318fd2659 (diff) |
Merge #13471: For AVX2 code, also check for AVX, XSAVE, and OS support
32d153fa360f73b4999701b97d55b12318fd2659 For AVX2 code, also check for AVX, XSAVE, and OS support (Pieter Wuille)
Pull request description:
Fixes #12903.
Tree-SHA512: 01e71efb5d3a43c49a145a5b1dc4fe7d0a491e1e78479e7df830a2aaac57c3dcfc316e28984c695206c76f93b68e4350fc037ca36756ca579b7070e39c835da2
-rw-r--r-- | src/crypto/sha256.cpp | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 100d0d1fac..e62ddc125e 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -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)); } + +/** 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 } // namespace @@ -544,6 +552,7 @@ std::string SHA256AutoDetect() { std::string ret = "standard"; #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; cpuid(1, 0, eax, ebx, ecx, edx); if ((ecx >> 19) & 1) { @@ -555,10 +564,14 @@ std::string SHA256AutoDetect() TransformD64_4way = sha256d64_sse41::Transform_4way; ret = "sse4(1way+4way)"; #if defined(ENABLE_AVX2) && !defined(BUILD_BITCOIN_INTERNAL) - cpuid(7, 0, eax, ebx, ecx, edx); - if ((ebx >> 5) & 1) { - TransformD64_8way = sha256d64_avx2::Transform_8way; - ret += ",avx2(8way)"; + if (((ecx >> 27) & 1) && ((ecx >> 28) & 1)) { // XSAVE and AVX + cpuid(7, 0, eax, ebx, ecx, edx); + if ((ebx >> 5) & 1) { // AVX2 flag + if (AVXEnabled()) { // OS has enabled AVX registers + TransformD64_8way = sha256d64_avx2::Transform_8way; + ret += ",avx2(8way)"; + } + } } #endif #else |