@@ -106,9 +106,11 @@ pub(crate) fn detect_features() -> cache::Initializer {
106106 {
107107 // borrows value till the end of this scope:
108108 let mut enable = |r, rb, f| {
109- if bit:: test ( r as usize , rb) {
109+ let present = bit:: test ( r as usize , rb) ;
110+ if present {
110111 value. set ( f as u32 ) ;
111112 }
113+ present
112114 } ;
113115
114116 enable ( proc_info_ecx, 0 , Feature :: sse3) ;
@@ -120,7 +122,7 @@ pub(crate) fn detect_features() -> cache::Initializer {
120122 enable ( proc_info_ecx, 22 , Feature :: movbe) ;
121123 enable ( proc_info_ecx, 23 , Feature :: popcnt) ;
122124 enable ( proc_info_ecx, 25 , Feature :: aes) ;
123- enable ( proc_info_ecx, 29 , Feature :: f16c) ;
125+ let f16c = enable ( proc_info_ecx, 29 , Feature :: f16c) ;
124126 enable ( proc_info_ecx, 30 , Feature :: rdrand) ;
125127 enable ( extended_features_ebx, 18 , Feature :: rdseed) ;
126128 enable ( extended_features_ebx, 19 , Feature :: adx) ;
@@ -216,7 +218,7 @@ pub(crate) fn detect_features() -> cache::Initializer {
216218 }
217219
218220 // FMA (uses 256-bit wide registers):
219- enable ( proc_info_ecx, 12 , Feature :: fma) ;
221+ let fma = enable ( proc_info_ecx, 12 , Feature :: fma) ;
220222
221223 // And AVX/AVX2:
222224 enable ( proc_info_ecx, 28 , Feature :: avx) ;
@@ -235,7 +237,11 @@ pub(crate) fn detect_features() -> cache::Initializer {
235237
236238 // For AVX-512 the OS also needs to support saving/restoring
237239 // the extended state, only then we enable AVX-512 support:
238- if os_avx512_support {
240+ // Also, Rust makes `avx512f` imply `fma` and `f16c`, because
241+ // otherwise the assembler is broken. But Intel doesn't guarantee
242+ // that `fma` and `f16c` are available with `avx512f`, so we
243+ // need to check for them separately.
244+ if os_avx512_support && f16c && fma {
239245 enable ( extended_features_ebx, 16 , Feature :: avx512f) ;
240246 enable ( extended_features_ebx, 17 , Feature :: avx512dq) ;
241247 enable ( extended_features_ebx, 21 , Feature :: avx512ifma) ;
0 commit comments