react-native-executorch 0.10.5 → 0.10.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. package/README.md +10 -1
  2. package/android/build.gradle.kts +4 -3
  3. package/ios/RnExecutorch.mm +15 -17
  4. package/lib/module/fetcher/fetcher.js +35 -122
  5. package/lib/module/fetcher/fetcher.js.map +1 -1
  6. package/lib/module/fetcher/telemetry.js +1 -1
  7. package/lib/module/index.js +12 -13
  8. package/lib/module/index.js.map +1 -1
  9. package/lib/module/models.js +4 -2
  10. package/lib/module/models.js.map +1 -1
  11. package/lib/typescript/src/fetcher/fetcher.d.ts +3 -7
  12. package/lib/typescript/src/fetcher/fetcher.d.ts.map +1 -1
  13. package/lib/typescript/src/models.d.ts.map +1 -1
  14. package/package.json +9 -7
  15. package/react-native-executorch.podspec +6 -2
  16. package/src/fetcher/fetcher.ts +38 -131
  17. package/src/fetcher/telemetry.ts +1 -1
  18. package/src/models.ts +6 -1
  19. package/third-party/common/phonemis/CMakeLists.txt +70 -14
  20. package/third-party/common/phonemis/README.md +183 -33
  21. package/third-party/common/phonemis/THIRD_PARTY_NOTICES.md +57 -0
  22. package/third-party/common/phonemis/knowledge/code_style.md +642 -0
  23. package/third-party/common/phonemis/licenses/Unicode-3.0.txt +39 -0
  24. package/third-party/common/phonemis/licenses/misaki-Apache-2.0.txt +201 -0
  25. package/third-party/common/phonemis/licenses/nlohmann-json-MIT.txt +21 -0
  26. package/third-party/common/phonemis/licenses/xsimd-BSD-3-Clause.txt +29 -0
  27. package/third-party/common/phonemis/src/phonemis/base/config.h +6 -0
  28. package/third-party/common/phonemis/src/phonemis/base/ipipeline.cpp +75 -0
  29. package/third-party/common/phonemis/src/phonemis/base/ipipeline.h +21 -0
  30. package/third-party/common/phonemis/src/phonemis/base/phonemizer/constants.h +2 -5
  31. package/third-party/common/phonemis/src/phonemis/base/phonemizer/lexicon_phonemizer.cpp +3 -4
  32. package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/neural_phonemizer.cpp +17 -8
  33. package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/neural_phonemizer.h +4 -0
  34. package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/tokenizer.cpp +21 -6
  35. package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/tokenizer.h +13 -4
  36. package/third-party/common/phonemis/src/phonemis/base/pipeline.cpp +8 -0
  37. package/third-party/common/phonemis/src/phonemis/base/pipeline.h +19 -0
  38. package/third-party/common/phonemis/src/phonemis/base/processor/common/conditions.cpp +37 -0
  39. package/third-party/common/phonemis/src/phonemis/base/processor/common/conditions.h +45 -0
  40. package/third-party/common/phonemis/src/phonemis/base/processor/common/constants.h +10 -0
  41. package/third-party/common/phonemis/src/phonemis/base/processor/common/context.cpp +105 -0
  42. package/third-party/common/phonemis/src/phonemis/base/processor/common/context.h +49 -0
  43. package/third-party/common/phonemis/src/phonemis/base/processor/common/document.cpp +173 -0
  44. package/third-party/common/phonemis/src/phonemis/base/processor/common/document.h +67 -0
  45. package/third-party/common/phonemis/src/phonemis/base/processor/common/text.cpp +75 -0
  46. package/third-party/common/phonemis/src/phonemis/base/processor/common/text.h +60 -0
  47. package/third-party/common/phonemis/src/phonemis/base/processor/common/types.h +18 -0
  48. package/third-party/common/phonemis/src/phonemis/base/processor/config.h +53 -0
  49. package/third-party/common/phonemis/src/phonemis/base/processor/layer.h +9 -7
  50. package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/constants.h +20 -0
  51. package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/layer.cpp +89 -0
  52. package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/layer.h +35 -0
  53. package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/types.h +16 -0
  54. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/kind.h +40 -0
  55. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/layer.h +382 -0
  56. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/notation.h +30 -0
  57. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/numerals.cpp +51 -0
  58. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/numerals.h +31 -0
  59. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern.h +30 -0
  60. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern_set.cpp +17 -0
  61. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern_set.h +31 -0
  62. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/patterns.cpp +811 -0
  63. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/patterns.h +285 -0
  64. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/primitives.cpp +64 -0
  65. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/primitives.h +23 -0
  66. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/types.h +94 -0
  67. package/third-party/common/phonemis/src/phonemis/base/processor/layers/sanitizer/layer.cpp +19 -0
  68. package/third-party/common/phonemis/src/phonemis/base/processor/{sanitizer_layer.h → layers/sanitizer/layer.h} +8 -8
  69. package/third-party/common/phonemis/src/phonemis/base/processor/layers/sym2word/layer.cpp +65 -0
  70. package/third-party/common/phonemis/src/phonemis/base/processor/layers/sym2word/layer.h +29 -0
  71. package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/layer.cpp +170 -0
  72. package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/layer.h +40 -0
  73. package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/types.h +25 -0
  74. package/third-party/common/phonemis/src/phonemis/base/processor/layers/trim/layer.cpp +47 -0
  75. package/third-party/common/phonemis/src/phonemis/base/processor/layers/trim/layer.h +19 -0
  76. package/third-party/common/phonemis/src/phonemis/base/processor/preprocessor.cpp +60 -0
  77. package/third-party/common/phonemis/src/phonemis/base/processor/preprocessor.h +45 -0
  78. package/third-party/common/phonemis/src/phonemis/base/processor/processor.cpp +6 -7
  79. package/third-party/common/phonemis/src/phonemis/base/processor/processor.h +14 -10
  80. package/third-party/common/phonemis/src/phonemis/base/tagger/hmm_tagger.cpp +89 -52
  81. package/third-party/common/phonemis/src/phonemis/base/tagger/hmm_tagger.h +16 -9
  82. package/third-party/common/phonemis/src/phonemis/base/tokenizer/tokenizer.cpp +13 -12
  83. package/third-party/common/phonemis/src/phonemis/lang/de/constants.h +183 -19
  84. package/third-party/common/phonemis/src/phonemis/lang/de/num2word.cpp +355 -309
  85. package/third-party/common/phonemis/src/phonemis/lang/de/num2word.h +42 -17
  86. package/third-party/common/phonemis/src/phonemis/lang/de/patterns.cpp +56 -0
  87. package/third-party/common/phonemis/src/phonemis/lang/de/patterns.h +15 -0
  88. package/third-party/common/phonemis/src/phonemis/lang/de/pipeline.h +3 -3
  89. package/third-party/common/phonemis/src/phonemis/lang/en/constants.h +181 -30
  90. package/third-party/common/phonemis/src/phonemis/lang/en/hmm_tagger.cpp +5 -7
  91. package/third-party/common/phonemis/src/phonemis/lang/en/num2word.cpp +232 -135
  92. package/third-party/common/phonemis/src/phonemis/lang/en/num2word.h +41 -16
  93. package/third-party/common/phonemis/src/phonemis/lang/en/pipeline.h +3 -10
  94. package/third-party/common/phonemis/src/phonemis/lang/es/constants.h +182 -60
  95. package/third-party/common/phonemis/src/phonemis/lang/es/num2word.cpp +247 -212
  96. package/third-party/common/phonemis/src/phonemis/lang/es/num2word.h +38 -18
  97. package/third-party/common/phonemis/src/phonemis/lang/es/patterns.cpp +50 -0
  98. package/third-party/common/phonemis/src/phonemis/lang/es/patterns.h +15 -0
  99. package/third-party/common/phonemis/src/phonemis/lang/es/pipeline.h +3 -3
  100. package/third-party/common/phonemis/src/phonemis/lang/fr/constants.h +152 -26
  101. package/third-party/common/phonemis/src/phonemis/lang/fr/num2word.cpp +252 -179
  102. package/third-party/common/phonemis/src/phonemis/lang/fr/num2word.h +38 -15
  103. package/third-party/common/phonemis/src/phonemis/lang/fr/patterns.cpp +83 -0
  104. package/third-party/common/phonemis/src/phonemis/lang/fr/patterns.h +15 -0
  105. package/third-party/common/phonemis/src/phonemis/lang/fr/pipeline.h +3 -3
  106. package/third-party/common/phonemis/src/phonemis/lang/hi/constants.h +62 -10
  107. package/third-party/common/phonemis/src/phonemis/lang/hi/num2word.cpp +74 -123
  108. package/third-party/common/phonemis/src/phonemis/lang/hi/num2word.h +27 -16
  109. package/third-party/common/phonemis/src/phonemis/lang/hi/pipeline.h +5 -3
  110. package/third-party/common/phonemis/src/phonemis/lang/it/constants.h +122 -42
  111. package/third-party/common/phonemis/src/phonemis/lang/it/num2word.cpp +200 -207
  112. package/third-party/common/phonemis/src/phonemis/lang/it/num2word.h +30 -18
  113. package/third-party/common/phonemis/src/phonemis/lang/it/patterns.cpp +25 -0
  114. package/third-party/common/phonemis/src/phonemis/lang/it/patterns.h +15 -0
  115. package/third-party/common/phonemis/src/phonemis/lang/it/pipeline.h +3 -3
  116. package/third-party/common/phonemis/src/phonemis/lang/pl/constants.h +346 -77
  117. package/third-party/common/phonemis/src/phonemis/lang/pl/num2word.cpp +631 -246
  118. package/third-party/common/phonemis/src/phonemis/lang/pl/num2word.h +47 -15
  119. package/third-party/common/phonemis/src/phonemis/lang/pl/pipeline.h +6 -6
  120. package/third-party/common/phonemis/src/phonemis/lang/pt/constants.h +201 -0
  121. package/third-party/common/phonemis/src/phonemis/lang/pt/num2word.cpp +365 -0
  122. package/third-party/common/phonemis/src/phonemis/lang/pt/num2word.h +53 -0
  123. package/third-party/common/phonemis/src/phonemis/lang/pt/pipeline.h +4 -2
  124. package/third-party/common/phonemis/src/phonemis/main.cpp +42 -11
  125. package/third-party/common/phonemis/src/phonemis/protophone/meta.h +24 -0
  126. package/third-party/common/phonemis/src/phonemis/protophone/numeric.h +26 -0
  127. package/third-party/common/phonemis/src/phonemis/protophone/protophone.cpp +525 -0
  128. package/third-party/common/phonemis/src/phonemis/protophone/protophone.h +80 -0
  129. package/third-party/common/phonemis/src/phonemis/protophone/tensor.h +76 -0
  130. package/third-party/common/phonemis/src/phonemis/protophone/tensor_utils.h +89 -0
  131. package/third-party/common/phonemis/src/phonemis/protophone/tensor_view.h +125 -0
  132. package/third-party/common/phonemis/src/phonemis/protophone/types.h +43 -0
  133. package/third-party/common/phonemis/src/phonemis/utils/strings.h +20 -14
  134. package/third-party/common/phonemis/src/phonemis/utils/unicode.h +15 -1
  135. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_arithmetic.hpp +267 -0
  136. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_bit.hpp +232 -0
  137. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_cast.hpp +43 -0
  138. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_complex.hpp +112 -0
  139. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_details.hpp +386 -0
  140. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_logical.hpp +240 -0
  141. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_math.hpp +2601 -0
  142. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_memory.hpp +1006 -0
  143. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_rounding.hpp +72 -0
  144. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_swizzle.hpp +260 -0
  145. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_trigo.hpp +996 -0
  146. package/third-party/common/phonemis/src/third-party/xsimd/arch/utils/shifts.hpp +82 -0
  147. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx.hpp +2111 -0
  148. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx2.hpp +1591 -0
  149. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx2_128.hpp +170 -0
  150. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512bw.hpp +724 -0
  151. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512cd.hpp +28 -0
  152. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512dq.hpp +270 -0
  153. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512er.hpp +17 -0
  154. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512f.hpp +2919 -0
  155. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512ifma.hpp +17 -0
  156. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512pf.hpp +17 -0
  157. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vbmi.hpp +76 -0
  158. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vbmi2.hpp +130 -0
  159. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vnni_avx512bw.hpp +17 -0
  160. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vnni_avx512vbmi2.hpp +17 -0
  161. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx_128.hpp +164 -0
  162. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avxvnni.hpp +17 -0
  163. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_common.hpp +26 -0
  164. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_common_fwd.hpp +127 -0
  165. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_constants.hpp +393 -0
  166. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_emulated.hpp +787 -0
  167. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_avx.hpp +93 -0
  168. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_avx2.hpp +46 -0
  169. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_sse.hpp +97 -0
  170. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma4.hpp +92 -0
  171. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_i8mm_neon64.hpp +17 -0
  172. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_isa.hpp +148 -0
  173. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_neon.hpp +3580 -0
  174. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_neon64.hpp +1614 -0
  175. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_rvv.hpp +1515 -0
  176. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_scalar.hpp +1210 -0
  177. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse2.hpp +2333 -0
  178. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse3.hpp +66 -0
  179. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse4_1.hpp +510 -0
  180. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse4_2.hpp +44 -0
  181. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_ssse3.hpp +186 -0
  182. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sve.hpp +1186 -0
  183. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_vsx.hpp +947 -0
  184. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_vxe.hpp +787 -0
  185. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_wasm.hpp +1819 -0
  186. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_arch.hpp +242 -0
  187. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_config.hpp +633 -0
  188. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features.hpp +50 -0
  189. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_arm.hpp +132 -0
  190. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_ppc.hpp +54 -0
  191. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_riscv.hpp +95 -0
  192. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_s390x.hpp +56 -0
  193. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_x86.hpp +1121 -0
  194. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpuid.hpp +144 -0
  195. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_getauxval.hpp +159 -0
  196. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_macros.hpp +78 -0
  197. package/third-party/common/phonemis/src/third-party/xsimd/math/xsimd_rem_pio2.hpp +707 -0
  198. package/third-party/common/phonemis/src/third-party/xsimd/memory/xsimd_aligned_allocator.hpp +349 -0
  199. package/third-party/common/phonemis/src/third-party/xsimd/memory/xsimd_alignment.hpp +102 -0
  200. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_all_registers.hpp +57 -0
  201. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_api.hpp +3106 -0
  202. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx2_register.hpp +57 -0
  203. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512bw_register.hpp +51 -0
  204. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512cd_register.hpp +51 -0
  205. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512dq_register.hpp +51 -0
  206. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512er_register.hpp +51 -0
  207. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512f_register.hpp +77 -0
  208. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512ifma_register.hpp +51 -0
  209. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512pf_register.hpp +51 -0
  210. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vbmi2_register.hpp +51 -0
  211. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vbmi_register.hpp +51 -0
  212. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vnni_avx512bw_register.hpp +54 -0
  213. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vnni_avx512vbmi2_register.hpp +53 -0
  214. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx_register.hpp +79 -0
  215. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avxvnni_register.hpp +44 -0
  216. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch.hpp +1666 -0
  217. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch_constant.hpp +572 -0
  218. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch_fwd.hpp +41 -0
  219. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_common_arch.hpp +49 -0
  220. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_emulated_register.hpp +80 -0
  221. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_avx2_register.hpp +50 -0
  222. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_avx_register.hpp +50 -0
  223. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_sse_register.hpp +50 -0
  224. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma4_register.hpp +50 -0
  225. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_i8mm_neon64_register.hpp +55 -0
  226. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_neon64_register.hpp +55 -0
  227. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_neon_register.hpp +130 -0
  228. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_register.hpp +96 -0
  229. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_rvv_register.hpp +491 -0
  230. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse2_register.hpp +59 -0
  231. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse3_register.hpp +49 -0
  232. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse4_1_register.hpp +48 -0
  233. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse4_2_register.hpp +48 -0
  234. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_ssse3_register.hpp +48 -0
  235. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sve_register.hpp +216 -0
  236. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_traits.hpp +409 -0
  237. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_utils.hpp +462 -0
  238. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_vsx_register.hpp +84 -0
  239. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_vxe_register.hpp +86 -0
  240. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_wasm_register.hpp +59 -0
  241. package/third-party/common/phonemis/src/third-party/xsimd/utils/bits.hpp +122 -0
  242. package/third-party/common/phonemis/src/third-party/xsimd/utils/xsimd_type_traits.hpp +145 -0
  243. package/third-party/common/phonemis/src/third-party/xsimd/xsimd.hpp +43 -0
  244. package/third-party/common/phonemis/src/phonemis/base/processor/constants.h +0 -11
  245. package/third-party/common/phonemis/src/phonemis/base/processor/num2word/config.h +0 -16
  246. package/third-party/common/phonemis/src/phonemis/base/processor/num2word/layer.cpp +0 -271
  247. package/third-party/common/phonemis/src/phonemis/base/processor/num2word/layer.h +0 -45
  248. package/third-party/common/phonemis/src/phonemis/base/processor/num2word/types.h +0 -29
  249. package/third-party/common/phonemis/src/phonemis/base/processor/sanitizer_layer.cpp +0 -22
  250. package/third-party/common/phonemis/src/phonemis/base/processor/trim_layer.cpp +0 -40
  251. package/third-party/common/phonemis/src/phonemis/base/processor/trim_layer.h +0 -22
@@ -0,0 +1,1121 @@
1
+ /***************************************************************************
2
+ * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
3
+ * Martin Renou *
4
+ * Copyright (c) QuantStack *
5
+ * Copyright (c) Serge Guelton *
6
+ * *
7
+ * Distributed under the terms of the BSD 3-Clause License. *
8
+ * *
9
+ * The full license is in the file LICENSE, distributed with this software. *
10
+ ****************************************************************************/
11
+
12
+ #ifndef XSIMD_CPU_FEATURES_X86_HPP
13
+ #define XSIMD_CPU_FEATURES_X86_HPP
14
+
15
+ #include <array>
16
+ #include <cassert>
17
+ #include <cstdint>
18
+ #include <cstring>
19
+ #include <type_traits>
20
+ #if XSIMD_CPP_VERSION >= 201703L
21
+ #include <string_view>
22
+ #endif
23
+
24
+ #include "../utils/bits.hpp"
25
+ #include "./xsimd_config.hpp"
26
+
27
+ #if XSIMD_TARGET_X86 && defined(_MSC_VER)
28
+ #include <intrin.h> // Contains the definition of __cpuidex
29
+ #endif
30
+
31
+ namespace xsimd
32
+ {
33
+ namespace detail
34
+ {
35
+ using x86_reg32_t = std::uint32_t;
36
+
37
+ using cpuid_reg_t = std::array<x86_reg32_t, 4>;
38
+
39
+ /**
40
+ * CPU Identification (CPUID) instruction results.
41
+ *
42
+ * The CPUID instruction provides detailed information about the processor,
43
+ * including supported instruction set extensions (SSE, AVX, AVX-512, etc.).
44
+ * This function is well defined on all architectures but will return all zeros
45
+ * on all non-x86 architectures.
46
+ *
47
+ * @param leaf The value inputted to the EAX register.
48
+ * @param subleaf The value inputted to the ECX register.
49
+ *
50
+ * @see https://en.wikipedia.org/wiki/CPUID
51
+ */
52
+ inline cpuid_reg_t x86_cpuid(int leaf, int subleaf = 0) noexcept;
53
+
54
+ inline x86_reg32_t x86_xcr0_low() noexcept;
55
+
56
+ /** A strongly type bitset for a 32 bits register. */
57
+ template <typename E>
58
+ using x86_reg32_bitset = utils::uint_bitset<E, x86_reg32_t>;
59
+
60
+ /** A wrapper to attach a register bitfield descriptor and its CPUID index. */
61
+ template <typename E, x86_reg32_t I>
62
+ struct x86_reg_id
63
+ {
64
+ static constexpr x86_reg32_t index = I;
65
+ using bits = E;
66
+
67
+ static_assert(index >= 0 && index < 4, "At most 4 register in CPUID");
68
+ };
69
+
70
+ /** Find the register id with index k. */
71
+ template <x86_reg32_t K, typename... reg_ids>
72
+ struct find_reg_k;
73
+
74
+ /** Find the register id with index k (empty / nothing found case). */
75
+ template <x86_reg32_t K, typename... reg_ids>
76
+ struct find_reg_k
77
+ {
78
+ using type = x86_reg_id<void, 0>;
79
+ };
80
+
81
+ /** Find the register id with index k (recursive case). */
82
+ template <x86_reg32_t K, typename reg_id_head, typename... reg_id_tail>
83
+ struct find_reg_k<K, reg_id_head, reg_id_tail...>
84
+ {
85
+ using type = std::conditional_t<
86
+ reg_id_head::index == K,
87
+ reg_id_head,
88
+ typename find_reg_k<K, reg_id_tail...>::type>;
89
+ };
90
+
91
+ /**
92
+ * A class with strongly typed bitfield for `CPUID` registers.
93
+ *
94
+ * The class stores a variable number of register (up to four) from the CPUID
95
+ * output. This is a space optimization to avoid storing many zeros in the
96
+ * final `x86_cpu_features`.
97
+ * As a result, some of the type aliases `eax`, `ebx`, `ecx`, `edx` may be `void`.
98
+ */
99
+ template <x86_reg32_t leaf_num, x86_reg32_t subleaf_num, typename... reg_ids>
100
+ class x86_cpuid_regs : private x86_reg32_bitset<typename reg_ids::bits>...
101
+ {
102
+ private:
103
+ static_assert(sizeof...(reg_ids) <= 4, "At most 4 register in CPUID");
104
+
105
+ /* Parse CPUINFO register value into individual bit components.*/
106
+ constexpr explicit x86_cpuid_regs(const cpuid_reg_t& regs) noexcept
107
+ : x86_reg32_bitset<typename reg_ids::bits>(regs[reg_ids::index])...
108
+ {
109
+ }
110
+
111
+ public:
112
+ static constexpr x86_reg32_t leaf = leaf_num;
113
+ static constexpr x86_reg32_t subleaf = subleaf_num;
114
+
115
+ using eax = typename find_reg_k<0, reg_ids...>::type::bits;
116
+ using ebx = typename find_reg_k<1, reg_ids...>::type::bits;
117
+ using ecx = typename find_reg_k<2, reg_ids...>::type::bits;
118
+ using edx = typename find_reg_k<3, reg_ids...>::type::bits;
119
+
120
+ inline static x86_cpuid_regs read()
121
+ {
122
+ return x86_cpuid_regs(detail::x86_cpuid(leaf, subleaf));
123
+ }
124
+
125
+ constexpr x86_cpuid_regs() noexcept = default;
126
+
127
+ // TODO(C++17) compact version for which this was designed.
128
+ // The else clause contains a very verbose port.
129
+ #if 0
130
+ using x86_reg32_bitset<typename reg_ids::bits>::all_bits_set...;
131
+ using x86_reg32_bitset<typename reg_ids::bits>::get_range...;
132
+ #else
133
+
134
+ private:
135
+ template <int N>
136
+ struct m_empty_reg
137
+ {
138
+ enum class type {};
139
+ };
140
+
141
+ using eax_or_empty = std::conditional_t<std::is_void<eax>::value, typename m_empty_reg<0>::type, eax>;
142
+ using ebx_or_empty = std::conditional_t<std::is_void<ebx>::value, typename m_empty_reg<1>::type, ebx>;
143
+ using ecx_or_empty = std::conditional_t<std::is_void<ecx>::value, typename m_empty_reg<2>::type, ecx>;
144
+ using edx_or_empty = std::conditional_t<std::is_void<edx>::value, typename m_empty_reg<3>::type, edx>;
145
+
146
+ public:
147
+ template <eax_or_empty... bits, typename T = eax, std::enable_if_t<!std::is_void<T>::value, int> = 0>
148
+ constexpr bool all_bits_set() const noexcept
149
+ {
150
+ return x86_reg32_bitset<eax>::template all_bits_set<bits...>();
151
+ }
152
+
153
+ template <eax_or_empty start, eax_or_empty end, typename T = eax, std::enable_if_t<!std::is_void<T>::value, int> = 0>
154
+ constexpr x86_reg32_t get_range() const noexcept
155
+ {
156
+ return x86_reg32_bitset<eax>::template get_range<start, end>();
157
+ }
158
+
159
+ template <ebx_or_empty... bits, typename T = ebx, std::enable_if_t<!std::is_void<T>::value, int> = 0>
160
+ constexpr bool all_bits_set() const noexcept
161
+ {
162
+ return x86_reg32_bitset<ebx>::template all_bits_set<bits...>();
163
+ }
164
+
165
+ template <ebx_or_empty start, ebx_or_empty end, typename T = ebx, std::enable_if_t<!std::is_void<T>::value, int> = 0>
166
+ constexpr x86_reg32_t get_range() const noexcept
167
+ {
168
+ return x86_reg32_bitset<ebx>::template get_range<start, end>();
169
+ }
170
+
171
+ template <ecx_or_empty... bits, typename T = ecx, std::enable_if_t<!std::is_void<T>::value, int> = 0>
172
+ constexpr bool all_bits_set() const noexcept
173
+ {
174
+ return x86_reg32_bitset<ecx>::template all_bits_set<bits...>();
175
+ }
176
+
177
+ template <ecx_or_empty start, ecx_or_empty end, typename T = ecx, std::enable_if_t<!std::is_void<T>::value, int> = 0>
178
+ constexpr x86_reg32_t get_range() const noexcept
179
+ {
180
+ return x86_reg32_bitset<ecx>::template get_range<start, end>();
181
+ }
182
+
183
+ template <edx_or_empty... bits, typename T = edx, std::enable_if_t<!std::is_void<T>::value, int> = 0>
184
+ constexpr bool all_bits_set() const noexcept
185
+ {
186
+ return x86_reg32_bitset<edx>::template all_bits_set<bits...>();
187
+ }
188
+
189
+ template <edx_or_empty start, edx_or_empty end, typename T = edx, std::enable_if_t<!std::is_void<T>::value, int> = 0>
190
+ constexpr x86_reg32_t get_range() const noexcept
191
+ {
192
+ return x86_reg32_bitset<edx>::template get_range<start, end>();
193
+ }
194
+
195
+ #endif // C++17
196
+ };
197
+
198
+ template <bool extended>
199
+ struct x86_cpuid_highest_func
200
+ {
201
+ private:
202
+ using x86_reg32_t = detail::x86_reg32_t;
203
+ using manufacturer_str = std::array<char, 3 * sizeof(x86_reg32_t)>;
204
+
205
+ public:
206
+ static constexpr x86_reg32_t leaf = extended ? 0x80000000 : 0x0;
207
+
208
+ inline static x86_cpuid_highest_func read()
209
+ {
210
+ auto regs = detail::x86_cpuid(0);
211
+ x86_cpuid_highest_func out {};
212
+ // Highest function parameter in EAX
213
+ out.m_highest_leaf = regs[0];
214
+
215
+ // Manufacturer string in EBX, EDX, ECX (in that order)
216
+ char* manuf = out.m_manufacturer_id.data();
217
+ std::memcpy(manuf + 0 * sizeof(x86_reg32_t), &regs[1], sizeof(x86_reg32_t));
218
+ std::memcpy(manuf + 1 * sizeof(x86_reg32_t), &regs[3], sizeof(x86_reg32_t));
219
+ std::memcpy(manuf + 2 * sizeof(x86_reg32_t), &regs[2], sizeof(x86_reg32_t));
220
+
221
+ return out;
222
+ }
223
+
224
+ constexpr x86_cpuid_highest_func() noexcept = default;
225
+
226
+ /**
227
+ * Highest available leaf in CPUID non-extended range.
228
+ *
229
+ * This is the highest function parameter (EAX) that can be passed to CPUID.
230
+ * This is valid in the specified range:
231
+ * - if `extended` is `false`, that is below `0x80000000`,
232
+ * - if `extended` is `true`, that is above `0x80000000`,
233
+ */
234
+ constexpr x86_reg32_t highest_leaf() const noexcept
235
+ {
236
+ return m_highest_leaf;
237
+ }
238
+
239
+ /**
240
+ * The manufacturer ID string in a static array.
241
+ *
242
+ * This raw character array is case specific and may contain both leading
243
+ * and trailing whitespaces.
244
+ * It cannot be assumed to be null terminated.
245
+ * This is not implemented for all manufacturer when `extended` is `true`.
246
+ */
247
+ constexpr manufacturer_str manufacturer_id_raw() const noexcept
248
+ {
249
+ return m_manufacturer_id;
250
+ }
251
+
252
+ #if XSIMD_CPP_VERSION >= 201703L
253
+ constexpr std::string_view manufacturer_id() const noexcept
254
+ {
255
+ return { m_manufacturer_id.data(), m_manufacturer_id.size() };
256
+ }
257
+ #endif
258
+
259
+ private:
260
+ manufacturer_str m_manufacturer_id {};
261
+ x86_reg32_t m_highest_leaf {};
262
+ };
263
+ }
264
+
265
+ /**
266
+ * Highest CPUID Function Parameter and Manufacturer ID (EAX=0).
267
+ *
268
+ * Returns the highest leaf value supported by CPUID in the standard range
269
+ * (below 0x80000000), and the processor manufacturer ID string.
270
+ *
271
+ * @see https://en.wikipedia.org/wiki/CPUID
272
+ */
273
+ using x86_cpuid_leaf0 = detail::x86_cpuid_highest_func<false>;
274
+
275
+ /**
276
+ * Known processor manufacturer ID strings returned by CPUID leaf 0.
277
+ *
278
+ * The 12-byte manufacturer ID is stored in EBX, EDX, ECX (in that order).
279
+ * Some strings are shared across physical CPUs, emulators, and virtual machines.
280
+ * Obscure, defunct, and soft-core CPUs are not represented; they map to `unknown`.
281
+ *
282
+ * @see https://en.wikipedia.org/wiki/CPUID
283
+ */
284
+ enum class x86_manufacturer
285
+ {
286
+ /**
287
+ * AMD ("AuthenticAMD", "AMD ISBETTER").
288
+ *
289
+ * "AMD ISBETTER" was used by early K5 engineering samples.
290
+ */
291
+ amd,
292
+ /**
293
+ * Intel ("GenuineIntel", "GenuineIotel").
294
+ *
295
+ * "GenuineIotel" is a rare typo variant seen on some chips.
296
+ */
297
+ intel,
298
+ /**
299
+ * VIA / Centaur ("CentaurHauls", "VIA VIA VIA ").
300
+ *
301
+ * Centaur Technology was acquired by VIA in 1999;
302
+ * older chips report "CentaurHauls", newer ones "VIA VIA VIA ".
303
+ */
304
+ via,
305
+ /** Zhaoxin (" Shanghai "). */
306
+ zhaoxin,
307
+ /** Hygon ("HygonGenuine"). */
308
+ hygon,
309
+ /**
310
+ * Transmeta ("TransmetaCPU", "GenuineTMx86").
311
+ *
312
+ * Two different ID strings were used across product lines.
313
+ */
314
+ transmeta,
315
+ /** MCST Elbrus ("E2K MACHINE "). */
316
+ elbrus,
317
+ /** Microsoft Virtual PC / x86-to-ARM ("Virtual CPU "). */
318
+ microsoft_vpc,
319
+ /** Unrecognized manufacturer ID string. */
320
+ unknown,
321
+ };
322
+
323
+ /**
324
+ * Parse a 12-byte CPUID manufacturer ID into an @ref x86_manufacturer value.
325
+ *
326
+ * The input is the raw character array returned by @ref x86_cpuid_leaf0::manufacturer_id_raw.
327
+ * Unrecognized strings map to @ref x86_manufacturer::unknown.
328
+ */
329
+ inline x86_manufacturer x86_parse_manufacturer(const std::array<char, 12>& id) noexcept
330
+ {
331
+ auto eq = [&id](const char(&s)[13]) noexcept -> bool
332
+ {
333
+ return std::memcmp(id.data(), s, 12) == 0;
334
+ };
335
+ if (eq("GenuineIntel") || eq("GenuineIotel"))
336
+ return x86_manufacturer::intel;
337
+ if (eq("AuthenticAMD") || eq("AMD ISBETTER"))
338
+ return x86_manufacturer::amd;
339
+ if (eq("CentaurHauls") || eq("VIA VIA VIA "))
340
+ return x86_manufacturer::via;
341
+ if (eq(" Shanghai "))
342
+ return x86_manufacturer::zhaoxin;
343
+ if (eq("HygonGenuine"))
344
+ return x86_manufacturer::hygon;
345
+ if (eq("TransmetaCPU") || eq("GenuineTMx86"))
346
+ return x86_manufacturer::transmeta;
347
+ if (eq("E2K MACHINE "))
348
+ return x86_manufacturer::elbrus;
349
+ if (eq("Virtual CPU "))
350
+ return x86_manufacturer::microsoft_vpc;
351
+ return x86_manufacturer::unknown;
352
+ };
353
+
354
+ /** Return a string representation of an @ref x86_manufacturer value. */
355
+ constexpr const char* x86_manufacturer_name(x86_manufacturer m) noexcept
356
+ {
357
+ switch (m)
358
+ {
359
+ case x86_manufacturer::intel:
360
+ return "intel";
361
+ case x86_manufacturer::amd:
362
+ return "amd";
363
+ case x86_manufacturer::via:
364
+ return "via";
365
+ case x86_manufacturer::zhaoxin:
366
+ return "zhaoxin";
367
+ case x86_manufacturer::hygon:
368
+ return "hygon";
369
+ case x86_manufacturer::transmeta:
370
+ return "transmeta";
371
+ case x86_manufacturer::elbrus:
372
+ return "elbrus";
373
+ case x86_manufacturer::microsoft_vpc:
374
+ return "microsoft_vpc";
375
+ case x86_manufacturer::unknown:
376
+ return "unknown";
377
+ }
378
+ return "invalid";
379
+ }
380
+
381
+ struct x86_cpuid_leaf1_traits
382
+ {
383
+ static constexpr detail::x86_reg32_t leaf = 1;
384
+ static constexpr detail::x86_reg32_t subleaf = 0;
385
+
386
+ enum class ecx
387
+ {
388
+ /* Streaming SIMD Extensions 3. */
389
+ sse3 = 0,
390
+ /* Supplemental Streaming SIMD Extensions 3. */
391
+ ssse3 = 9,
392
+ /* Fused multiply-add with 3 operands (FMA3). */
393
+ fma3 = 12,
394
+ /* Streaming SIMD Extensions 4.1. */
395
+ sse4_1 = 19,
396
+ /* Streaming SIMD Extensions 4.2. */
397
+ sse4_2 = 20,
398
+ /* Population count instruction (POPCNT). */
399
+ popcnt = 23,
400
+ /* Advanced Encryption Standard instruction set. */
401
+ aes_ni = 25,
402
+ /* OS has enabled XSAVE/XRSTOR for extended processor state management. */
403
+ osxsave = 27,
404
+ /* Advanced Vector Extensions (256-bit SIMD). */
405
+ avx = 28,
406
+ /* Half to single floating point conversion. */
407
+ f16c = 29,
408
+ /* On-chip random number generator. */
409
+ rdrnd = 30,
410
+ };
411
+ enum class edx
412
+ {
413
+ /* Streaming SIMD Extensions 2. */
414
+ sse2 = 26,
415
+ };
416
+
417
+ using regs_t = detail::x86_cpuid_regs<leaf, subleaf,
418
+ detail::x86_reg_id<ecx, 2>,
419
+ detail::x86_reg_id<edx, 3>>;
420
+ };
421
+
422
+ /**
423
+ * Processor Info and Feature Bits.
424
+ *
425
+ * Utility class that can read and parse the registers for the first leaf level
426
+ * of the CPUID instruction.
427
+ * This is well defined on all architectures but will return all false on all
428
+ * non-x86 architectures.
429
+ *
430
+ * @see https://en.wikipedia.org/wiki/CPUID
431
+ */
432
+ using x86_cpuid_leaf1 = typename x86_cpuid_leaf1_traits::regs_t;
433
+
434
+ struct x86_cpuid_leaf7_traits
435
+ {
436
+ static constexpr detail::x86_reg32_t leaf = 7;
437
+ static constexpr detail::x86_reg32_t subleaf = 0;
438
+
439
+ enum class eax
440
+ {
441
+ /* Start bit for the encoding of the highest subleaf available. */
442
+ highest_subleaf_start = 0,
443
+ /* End bit for the encoding of the highest subleaf available. */
444
+ highest_subleaf_end = 32,
445
+ };
446
+ enum class ebx
447
+ {
448
+ /* Bit Manipulation Instruction Set 1. */
449
+ bmi1 = 3,
450
+ /* Advanced Vector Extensions 2 (integer 256-bit SIMD). */
451
+ avx2 = 5,
452
+ /* Bit Manipulation Instruction Set 2. */
453
+ bmi2 = 8,
454
+ /* AVX-512 Foundation instructions. */
455
+ avx512f = 16,
456
+ /* AVX-512 Doubleword and Quadword instructions. */
457
+ avx512dq = 17,
458
+ /* Low-level access to the entropy-generating hardware. */
459
+ rdseed = 18,
460
+ /* Intel arbitrary precision add carry. */
461
+ adx = 19,
462
+ /* AVX-512 Integer Fused Multiply-Add instructions. */
463
+ avx512ifma = 21,
464
+ /* AVX-512 Prefetch instructions. */
465
+ avx512pf = 26,
466
+ /* AVX-512 Exponential and Reciprocal instructions. */
467
+ avx512er = 27,
468
+ /* AVX-512 Conflict Detection instructions. */
469
+ avx512cd = 28,
470
+ /* Sha-1 and Sha-256 extension. */
471
+ sha = 29,
472
+ /* AVX-512 Byte and Word instructions. */
473
+ avx512bw = 30,
474
+ /* AVX-512 Vector Length Extensions for xmm and ymm registers. */
475
+ avx512vl = 31,
476
+ };
477
+ enum class ecx
478
+ {
479
+ /* AVX-512 Vector Bit Manipulation instructions. */
480
+ avx512vbmi = 1,
481
+ /* AVX-512 Vector Bit Manipulation instructions 2. */
482
+ avx512vbmi2 = 6,
483
+ /* Galois Field instructions. */
484
+ gfni = 8,
485
+ /* Vector Advanced Encryption Standard instructions. */
486
+ vaes = 9,
487
+ /* Carry-less multiplication quadword instruction. */
488
+ vpclmulqdq = 10,
489
+ /* AVX-512 Vector Neural Network instructions. */
490
+ avx512vnni_bw = 11,
491
+ /* AVX-512 bit algorithm instructions (BITALG). */
492
+ avx512_bitalg = 12,
493
+ /* AVX-512 vector population count for doubleword and quadword. */
494
+ avx512_vpopcntdq = 14,
495
+ };
496
+ enum class edx
497
+ {
498
+ /* AVX-512 4-register neural network instructions (word variable precision). */
499
+ avx512_4vnniw = 2,
500
+ /* AVX-512 4-register multiply-accumulate single precision. */
501
+ avx512_4fmaps = 3,
502
+ /* AVX-512 intersect pairs of packed doubleword/quadword integers. */
503
+ avx512_vp2intersect = 8,
504
+ /* AVX-512 16-bit floating-point instructions. */
505
+ avx512_fp16 = 23,
506
+
507
+ };
508
+
509
+ using regs_t = detail::x86_cpuid_regs<leaf, subleaf,
510
+ detail::x86_reg_id<eax, 0>,
511
+ detail::x86_reg_id<ebx, 1>,
512
+ detail::x86_reg_id<ecx, 2>,
513
+ detail::x86_reg_id<edx, 3>>;
514
+ };
515
+
516
+ /**
517
+ * Extended Feature Bits (EAX=7, ECX=0).
518
+ *
519
+ * Utility class that can read and parse the registers for the extended
520
+ * feature bits leaf of the CPUID instruction.
521
+ * This is well defined on all architectures but will return all false on all
522
+ * non-x86 architectures.
523
+ *
524
+ * @see https://en.wikipedia.org/wiki/CPUID
525
+ */
526
+ using x86_cpuid_leaf7 = typename x86_cpuid_leaf7_traits::regs_t;
527
+
528
+ struct x86_cpuid_leaf7sub1_traits
529
+ {
530
+ static constexpr detail::x86_reg32_t leaf = 7;
531
+ static constexpr detail::x86_reg32_t subleaf = 1;
532
+
533
+ enum class eax
534
+ {
535
+ /* AVX (VEX-encoded) Vector Neural Network instructions. */
536
+ avxvnni = 4,
537
+ /* AVX-512 BFloat16 instructions. */
538
+ avx512_bf16 = 5,
539
+ };
540
+
541
+ using regs_t = detail::x86_cpuid_regs<leaf, subleaf,
542
+ detail::x86_reg_id<eax, 0>>;
543
+ };
544
+
545
+ /**
546
+ * Extended Feature Bits (EAX=7, ECX=1).
547
+ *
548
+ * Utility class that can read and parse the registers for the extended
549
+ * feature bits, subleaf 1, of the CPUID instruction.
550
+ * This is well defined on all architectures but will return all false on all
551
+ * non-x86 architectures.
552
+ *
553
+ * @see https://en.wikipedia.org/wiki/CPUID
554
+ */
555
+ using x86_cpuid_leaf7sub1 = typename x86_cpuid_leaf7sub1_traits::regs_t;
556
+
557
+ /**
558
+ * Highest Extended CPUID Function Parameter (EAX=0x80000000).
559
+ *
560
+ * Returns the highest leaf value supported by CPUID in the extended range
561
+ * (at or above 0x80000000), and the processor manufacturer ID string.
562
+ *
563
+ * @see https://en.wikipedia.org/wiki/CPUID
564
+ */
565
+ using x86_cpuid_leaf80000000 = detail::x86_cpuid_highest_func<true>;
566
+
567
+ struct x86_cpuid_leaf80000001_traits
568
+ {
569
+ static constexpr detail::x86_reg32_t leaf = 0x80000001;
570
+ static constexpr detail::x86_reg32_t subleaf = 0;
571
+
572
+ enum class ecx
573
+ {
574
+ /* AMD Fused multiply-add with 4 operands (FMA4). */
575
+ fma4 = 16,
576
+ };
577
+
578
+ using regs_t = detail::x86_cpuid_regs<leaf, subleaf,
579
+ detail::x86_reg_id<ecx, 2>>;
580
+ };
581
+
582
+ /**
583
+ * Extended Processor Info and Feature Bits.
584
+ *
585
+ * Utility class that can read and parse the registers for the extended
586
+ * processor info leaf of the CPUID instruction.
587
+ * This is well defined on all architectures but will return all false on all
588
+ * non-x86 architectures.
589
+ *
590
+ * @see https://en.wikipedia.org/wiki/CPUID
591
+ */
592
+ using x86_cpuid_leaf80000001 = typename x86_cpuid_leaf80000001_traits::regs_t;
593
+
594
+ /*
595
+ * Extended Control Register 0 (XCR0).
596
+ *
597
+ * Operating systems can explicitly disable the usage of instruction set (such
598
+ * as SSE or AVX extensions) by setting an appropriate flag in XCR0 register.
599
+ * This utility parses such bit values.
600
+ *
601
+ * @see https://docs.kernel.org/admin-guide/hw-vuln/gather_data_sampling.html
602
+ */
603
+ class x86_xcr0
604
+ {
605
+ public:
606
+ enum class xcr0
607
+ {
608
+ /** x87 FPU/MMX support (must be 1). */
609
+ x87 = 0,
610
+ /** XSAVE support for MXCSR and XMM registers. */
611
+ sse = 1,
612
+ /** AVX enabled and XSAVE support for upper halves of YMM registers. */
613
+ avx = 2,
614
+ /** MPX enabled and XSAVE support for BND0-BND3 registers. */
615
+ bndreg = 3,
616
+ /** MPX enabled and XSAVE support for BNDCFGU and BNDSTATUS registers. */
617
+ bndcsr = 4,
618
+ /** AVX-512 enabled and XSAVE support for opmask registers k0-k7. */
619
+ opmask = 5,
620
+ /** AVX-512 enabled and XSAVE support for upper halves of lower ZMM registers. */
621
+ zmm_hi256 = 6,
622
+ /** AVX-512 enabled and XSAVE support for upper ZMM registers. */
623
+ hi16_zmm = 7,
624
+ /** Saving/restoring Intel Processor Trace state via XSAVE enabled.*/
625
+ processor_trace = 8,
626
+ /** XSAVE support for PKRU register. */
627
+ pkru = 9,
628
+ };
629
+
630
+ /**
631
+ * Create a default value with only SSE enabled.
632
+ *
633
+ * AVX and AVX512 strictly require OSXSAVE to be enabled by the OS.
634
+ * If OSXSAVE is disabled (e.g., via bcdedit /set xsavedisable 1), AVX state won't
635
+ * be preserved across context switches, so AVX cannot be used.
636
+ * SSE is therefore the only value safe to assume.
637
+ */
638
+ constexpr static x86_xcr0 safe_default() noexcept
639
+ {
640
+ x86_reg32_t low = {};
641
+ low = utils::make_bit_mask(static_cast<x86_reg32_t>(xcr0::sse));
642
+ return x86_xcr0(low);
643
+ }
644
+
645
+ /**
646
+ * Read the XCR0 register from the CPU if on the correct architecture.
647
+ *
648
+ * This is only safe to call if bit 18 of CR4.OSXSAVE has been set.
649
+ *
650
+ * @see cpu_id::osxsave
651
+ */
652
+ inline static x86_xcr0 read()
653
+ {
654
+ assert(x86_cpuid_leaf1::read().all_bits_set<x86_cpuid_leaf1::ecx::osxsave>());
655
+ return x86_xcr0(detail::x86_xcr0_low());
656
+ }
657
+
658
+ template <xcr0... bits>
659
+ constexpr bool all_bits_set() const noexcept
660
+ {
661
+ return m_low.all_bits_set<bits...>();
662
+ }
663
+
664
+ /** Create a value which return false to everything. */
665
+ constexpr x86_xcr0() noexcept = default;
666
+
667
+ private:
668
+ using x86_reg32_t = detail::x86_reg32_t;
669
+
670
+ using xcr0_reg_t = detail::x86_reg32_bitset<xcr0>;
671
+
672
+ /** Parse a XCR0 value into individual components. */
673
+ constexpr explicit x86_xcr0(x86_reg32_t low) noexcept
674
+ : m_low(low)
675
+ {
676
+ }
677
+
678
+ xcr0_reg_t m_low {};
679
+ };
680
+
681
+ /**
682
+ * Orchestrator for `CPUID` calls.
683
+ *
684
+ * This class orchestrate `CPUID` and `XCR0` calls so that they are made in the appropriate
685
+ * order. It also implements lazy calling and cache mechanism around those calls.
686
+ * Works on all platforms, and return all zeros on non `x86` platforms.
687
+ */
688
+ class x86_cpu_features_backend_cpuid
689
+ {
690
+ public:
691
+ x86_cpu_features_backend_cpuid() noexcept = default;
692
+
693
+ inline x86_xcr0 const& xcr0() const noexcept;
694
+ inline x86_cpuid_leaf0 const& leaf0() const;
695
+ inline x86_cpuid_leaf80000000 const& leaf80000000() const;
696
+ inline x86_cpuid_leaf1 const& leaf1() const;
697
+ inline x86_cpuid_leaf7 const& leaf7() const;
698
+ inline x86_cpuid_leaf7sub1 const& leaf7sub1() const;
699
+ inline x86_cpuid_leaf80000001 const& leaf80000001() const;
700
+
701
+ private:
702
+ enum class status
703
+ {
704
+ leaf0_valid = 0,
705
+ leaf1_valid = 1,
706
+ leaf7_valid = 2,
707
+ leaf7sub1_valid = 3,
708
+ leaf80000000_valid = 4,
709
+ leaf80000001_valid = 5,
710
+ xcr0_valid = 6,
711
+ };
712
+
713
+ using status_bitset = utils::uint_bitset<status, std::uint32_t>;
714
+
715
+ mutable x86_cpuid_leaf0 m_leaf0 {};
716
+ mutable x86_cpuid_leaf1 m_leaf1 {};
717
+ mutable x86_cpuid_leaf7 m_leaf7 {};
718
+ mutable x86_cpuid_leaf7sub1 m_leaf7sub1 {};
719
+ mutable x86_cpuid_leaf80000000 m_leaf80000000 {};
720
+ mutable x86_cpuid_leaf80000001 m_leaf80000001 {};
721
+ mutable x86_xcr0 m_xcr0 {};
722
+ mutable status_bitset m_status {};
723
+
724
+ inline bool osxsave() const noexcept;
725
+
726
+ /**
727
+ * Internal utility to lazily read and cache a CPUID leaf.
728
+ *
729
+ * @tparam status_id The status bit tracking whether this leaf has been read and cached.
730
+ * @tparam L The CPUID leaf type (e.g. x86_cpuid_leaf1, x86_cpuid_leaf7).
731
+ * @param leaf_cache A non-const reference to the class member that stores the leaf
732
+ * value. It must be non-const because this function may write to it on first
733
+ * call. It is passed explicitly (rather than accessed via `this`) to allow
734
+ * factoring the caching logic across different leaf members.
735
+ * @return A const reference to `leaf_cache`. The non-const input / const-ref output
736
+ * asymmetry is intentional: callers must not modify the cached value, but
737
+ * this function needs write access to populate it.
738
+ *
739
+ * On first call, checks whether the leaf number is within the range advertised as
740
+ * supported by CPUID (via leaf 0 for the standard range, leaf 0x80000000 for the
741
+ * extended range). If supported, reads the leaf from the CPU; otherwise leaves
742
+ * `leaf_cache` at its zero-initialized default (all feature bits false). Either
743
+ * way, `status_id` is set so subsequent calls return immediately.
744
+ */
745
+ template <status status_id, typename L>
746
+ inline auto const& safe_read_leaf(L& leaf_cache) const;
747
+ };
748
+
749
+ /**
750
+ * No-Op orchestrator for `CPUID` calls
751
+ *
752
+ * This does nothing and return zero-constructed objects on all calls.
753
+ * This is meant as an optimization on non `x86` platforms as the
754
+ * `x86_cpu_features_backend_cpuid` can be slightly large (hundred of bytes).
755
+ */
756
+ class x86_cpu_features_backend_noop
757
+ {
758
+ public:
759
+ constexpr x86_xcr0 xcr0() const noexcept { return {}; }
760
+ constexpr x86_cpuid_leaf0 leaf0() const { return {}; }
761
+ constexpr x86_cpuid_leaf80000000 leaf80000000() const { return {}; }
762
+ constexpr x86_cpuid_leaf1 leaf1() const { return {}; }
763
+ constexpr x86_cpuid_leaf7 leaf7() const { return {}; }
764
+ constexpr x86_cpuid_leaf7sub1 leaf7sub1() const { return {}; }
765
+ constexpr x86_cpuid_leaf80000001 leaf80000001() const { return {}; }
766
+ };
767
+
768
+ #if XSIMD_TARGET_X86
769
+ using x86_cpu_features_backend_default = x86_cpu_features_backend_cpuid;
770
+ #else
771
+ using x86_cpu_features_backend_default = x86_cpu_features_backend_noop;
772
+ #endif
773
+
774
+ /**
775
+ * An opiniated CPU feature detection utility for x86.
776
+ *
777
+ * These are high level features that combine multiple registers reads in sequence.
778
+ * Instead of looking directly at raw CPUID results, this utility also checks that
779
+ * permissions (e.g. OSXSAVE) are enabled, and otherwise return conservative defaults.
780
+ *
781
+ * This is well defined on all architectures. It will always return false on
782
+ * non-x86 architectures.
783
+ */
784
+ class x86_cpu_features : private x86_cpu_features_backend_default
785
+ {
786
+ public:
787
+ x86_cpu_features() noexcept = default;
788
+
789
+ inline bool sse_enabled() const noexcept
790
+ {
791
+ return xcr0().all_bits_set<x86_xcr0::xcr0::sse>();
792
+ }
793
+
794
+ inline bool avx_enabled() const noexcept
795
+ {
796
+ // Check both SSE and AVX bits even though AVX must imply SSE
797
+ return xcr0().all_bits_set<x86_xcr0::xcr0::sse, x86_xcr0::xcr0::avx>();
798
+ }
799
+
800
+ inline bool avx512_enabled() const noexcept
801
+ {
802
+ // Check all SSE, AVX, optmask, and AVX512 bits even though AVX512 must
803
+ // imply AVX, SSE, and masked operations.
804
+ return xcr0().all_bits_set<x86_xcr0::xcr0::sse, x86_xcr0::xcr0::avx, x86_xcr0::xcr0::opmask, x86_xcr0::xcr0::zmm_hi256>();
805
+ }
806
+
807
+ /**
808
+ * The manufacturer ID string in a static array.
809
+ *
810
+ * This raw character array is case specific and may contain both leading
811
+ * and trailing whitespaces.
812
+ * It cannot be assumed to be null terminated.
813
+ */
814
+ inline auto manufacturer_id_raw() const noexcept
815
+ {
816
+ return leaf0().manufacturer_id_raw();
817
+ }
818
+
819
+ #if XSIMD_CPP_VERSION >= 201703L
820
+ inline std::string_view manufacturer_id() const noexcept
821
+ {
822
+ return leaf0().manufacturer_id();
823
+ }
824
+ #endif
825
+
826
+ /** The manufacturer ID string parsed into known common vendors. */
827
+ inline x86_manufacturer known_manufacturer() const noexcept
828
+ {
829
+ return x86_parse_manufacturer(manufacturer_id_raw());
830
+ }
831
+
832
+ /**
833
+ * Indicates whether the OS has enabled extended state management.
834
+ *
835
+ * When true, the OS has set bit 18 (OSXSAVE) in the CR4 control register,
836
+ * enabling the XGETBV/XSETBV instructions to access XCR0 and support
837
+ * processor extended state management using XSAVE/XRSTOR.
838
+ *
839
+ * This value is read from CPUID leaf 0x1, ECX bit 27, which reflects
840
+ * the state of CR4.OSXSAVE.
841
+ */
842
+ inline bool osxsave() const noexcept { return leaf1().all_bits_set<x86_cpuid_leaf1::ecx::osxsave>(); }
843
+
844
+ inline bool sse2() const noexcept { return sse_enabled() && leaf1().all_bits_set<x86_cpuid_leaf1::edx::sse2>(); }
845
+
846
+ inline bool sse3() const noexcept { return sse_enabled() && leaf1().all_bits_set<x86_cpuid_leaf1::ecx::sse3>(); }
847
+
848
+ inline bool ssse3() const noexcept { return sse_enabled() && leaf1().all_bits_set<x86_cpuid_leaf1::ecx::ssse3>(); }
849
+
850
+ inline bool sse4_1() const noexcept { return sse_enabled() && leaf1().all_bits_set<x86_cpuid_leaf1::ecx::sse4_1>(); }
851
+
852
+ inline bool sse4_2() const noexcept { return sse_enabled() && leaf1().all_bits_set<x86_cpuid_leaf1::ecx::sse4_2>(); }
853
+
854
+ inline bool popcnt() const noexcept { return leaf1().all_bits_set<x86_cpuid_leaf1::ecx::popcnt>(); }
855
+
856
+ inline bool fma3() const noexcept { return sse_enabled() && leaf1().all_bits_set<x86_cpuid_leaf1::ecx::fma3>(); }
857
+
858
+ inline bool avx() const noexcept { return avx_enabled() && leaf1().all_bits_set<x86_cpuid_leaf1::ecx::avx>(); }
859
+
860
+ inline bool avx_128() const noexcept { return sse_enabled() && leaf1().all_bits_set<x86_cpuid_leaf1::ecx::avx>(); }
861
+
862
+ inline bool aes_ni() const noexcept { return sse_enabled() && leaf1().all_bits_set<x86_cpuid_leaf1::ecx::aes_ni>(); }
863
+
864
+ inline bool f16c() const noexcept { return avx_enabled() && leaf1().all_bits_set<x86_cpuid_leaf1::ecx::f16c>(); }
865
+
866
+ inline bool rdrnd() const noexcept { return leaf1().all_bits_set<x86_cpuid_leaf1::ecx::rdrnd>(); }
867
+
868
+ inline bool bmi1() const noexcept { return leaf7().all_bits_set<x86_cpuid_leaf7::ebx::bmi1>(); }
869
+
870
+ inline bool avx2() const noexcept { return avx_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ebx::avx2>(); }
871
+
872
+ inline bool avx2_128() const noexcept { return sse_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ebx::avx2>(); }
873
+
874
+ inline bool bmi2() const noexcept { return leaf7().all_bits_set<x86_cpuid_leaf7::ebx::bmi2>(); }
875
+
876
+ inline bool avx512f() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ebx::avx512f>(); }
877
+
878
+ inline bool avx512dq() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ebx::avx512dq>(); }
879
+
880
+ inline bool rdseed() const noexcept { return leaf7().all_bits_set<x86_cpuid_leaf7::ebx::rdseed>(); }
881
+
882
+ inline bool adx() const noexcept { return leaf7().all_bits_set<x86_cpuid_leaf7::ebx::adx>(); }
883
+
884
+ inline bool avx512ifma() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ebx::avx512ifma>(); }
885
+
886
+ inline bool avx512pf() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ebx::avx512pf>(); }
887
+
888
+ inline bool avx512er() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ebx::avx512er>(); }
889
+
890
+ inline bool avx512cd() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ebx::avx512cd>(); }
891
+
892
+ inline bool sha() const noexcept { return leaf7().all_bits_set<x86_cpuid_leaf7::ebx::sha>(); }
893
+
894
+ inline bool avx512bw() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ebx::avx512bw>(); }
895
+
896
+ inline bool avx512vl() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ebx::avx512vl>(); }
897
+
898
+ inline bool avx512vbmi() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ecx::avx512vbmi>(); }
899
+
900
+ inline bool avx512vbmi2() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ecx::avx512vbmi2>(); }
901
+
902
+ inline bool gfni() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ecx::gfni>(); }
903
+
904
+ inline bool vaes() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ecx::vaes>(); }
905
+
906
+ inline bool vpclmulqdq() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ecx::vpclmulqdq>(); }
907
+
908
+ inline bool avx512vnni_bw() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ecx::avx512vnni_bw>(); }
909
+
910
+ inline bool avx512_bitalg() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ecx::avx512_bitalg>(); }
911
+
912
+ inline bool avx512_vpopcntdq() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::ecx::avx512_vpopcntdq>(); }
913
+
914
+ inline bool avx512_4vnniw() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::edx::avx512_4vnniw>(); }
915
+
916
+ inline bool avx512_4fmaps() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::edx::avx512_4fmaps>(); }
917
+
918
+ inline bool avx512_vp2intersect() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::edx::avx512_vp2intersect>(); }
919
+
920
+ inline bool avx512_fp16() const noexcept { return avx512_enabled() && leaf7().all_bits_set<x86_cpuid_leaf7::edx::avx512_fp16>(); }
921
+
922
+ inline bool avxvnni() const noexcept { return avx_enabled() && leaf7sub1().all_bits_set<x86_cpuid_leaf7sub1::eax::avxvnni>(); }
923
+
924
+ inline bool avx512_bf16() const noexcept { return avx512_enabled() && leaf7sub1().all_bits_set<x86_cpuid_leaf7sub1::eax::avx512_bf16>(); }
925
+
926
+ inline bool fma4() const noexcept { return avx_enabled() && leaf80000001().all_bits_set<x86_cpuid_leaf80000001::ecx::fma4>(); }
927
+ };
928
+
929
+ /********************
930
+ * Implementation *
931
+ ********************/
932
+
933
+ template <x86_cpu_features_backend_cpuid::status status_id, typename L>
934
+ inline auto const& x86_cpu_features_backend_cpuid::safe_read_leaf(L& leaf_cache) const
935
+ {
936
+ // Check if already initialized
937
+ if (m_status.bit_is_set<status_id>())
938
+ {
939
+ return leaf_cache;
940
+ }
941
+
942
+ // Limit where we need to check leaf0 or leaf 80000000.
943
+ constexpr auto extended_threshold = x86_cpuid_leaf80000000::leaf;
944
+
945
+ // Check if it is safe to call CPUID with this value.
946
+ // First we identify if the leaf is in the regular or extended range.
947
+ // TODO(C++17): if constexpr
948
+ if (L::leaf < extended_threshold)
949
+ {
950
+ // Check leaf0 in regular range
951
+ if (L::leaf <= leaf0().highest_leaf())
952
+ {
953
+ leaf_cache = L::read();
954
+ }
955
+ }
956
+ else
957
+ {
958
+ // Check leaf80000000 in extended range
959
+ if (L::leaf <= leaf80000000().highest_leaf())
960
+ {
961
+ leaf_cache = L::read();
962
+ }
963
+ }
964
+
965
+ // Mark as valid in all cases, including if it was not read.
966
+ // In this case it will be filled with zeros (all false).
967
+ m_status.set_bit<status_id>();
968
+ return leaf_cache;
969
+ }
970
+
971
+ inline x86_xcr0 const& x86_cpu_features_backend_cpuid::xcr0() const noexcept
972
+ {
973
+ if (!m_status.bit_is_set<status::xcr0_valid>())
974
+ {
975
+ m_xcr0 = osxsave() ? x86_xcr0::read() : x86_xcr0::safe_default();
976
+ m_status.set_bit<status::xcr0_valid>();
977
+ }
978
+ return m_xcr0;
979
+ }
980
+
981
+ inline x86_cpuid_leaf0 const& x86_cpu_features_backend_cpuid::leaf0() const
982
+ {
983
+ if (!m_status.bit_is_set<status::leaf0_valid>())
984
+ {
985
+ m_leaf0 = x86_cpuid_leaf0::read();
986
+ m_status.set_bit<status::leaf0_valid>();
987
+ }
988
+ return m_leaf0;
989
+ }
990
+
991
+ inline x86_cpuid_leaf80000000 const& x86_cpu_features_backend_cpuid::leaf80000000() const
992
+ {
993
+ if (!m_status.bit_is_set<status::leaf80000000_valid>())
994
+ {
995
+ m_leaf80000000 = x86_cpuid_leaf80000000::read();
996
+ m_status.set_bit<status::leaf80000000_valid>();
997
+ }
998
+ return m_leaf80000000;
999
+ }
1000
+
1001
+ inline x86_cpuid_leaf1 const& x86_cpu_features_backend_cpuid::leaf1() const
1002
+ {
1003
+ return safe_read_leaf<status::leaf1_valid>(m_leaf1);
1004
+ }
1005
+
1006
+ inline x86_cpuid_leaf7 const& x86_cpu_features_backend_cpuid::leaf7() const
1007
+ {
1008
+ return safe_read_leaf<status::leaf7_valid>(m_leaf7);
1009
+ }
1010
+
1011
+ inline x86_cpuid_leaf7sub1 const& x86_cpu_features_backend_cpuid::leaf7sub1() const
1012
+ {
1013
+ // Check if already initialized
1014
+ if (m_status.bit_is_set<status::leaf7sub1_valid>())
1015
+ {
1016
+ return m_leaf7sub1;
1017
+ }
1018
+
1019
+ // Check if safe to call CPUID with this value as subleaf.
1020
+ constexpr auto start = x86_cpuid_leaf7::eax::highest_subleaf_start;
1021
+ constexpr auto end = x86_cpuid_leaf7::eax::highest_subleaf_end;
1022
+ const auto highest_subleaf7 = leaf7().get_range<start, end>();
1023
+ if (x86_cpuid_leaf7sub1::subleaf <= highest_subleaf7)
1024
+ {
1025
+ m_leaf7sub1 = x86_cpuid_leaf7sub1::read();
1026
+ }
1027
+
1028
+ // Mark as valid in all cases, including if it was not read.
1029
+ // In this case it will be filled with zeros (all false).
1030
+ m_status.set_bit<status::leaf7sub1_valid>();
1031
+ return m_leaf7sub1;
1032
+ }
1033
+
1034
+ inline x86_cpuid_leaf80000001 const& x86_cpu_features_backend_cpuid::leaf80000001() const
1035
+ {
1036
+ return safe_read_leaf<status::leaf80000001_valid>(m_leaf80000001);
1037
+ }
1038
+
1039
+ inline bool x86_cpu_features_backend_cpuid::osxsave() const noexcept
1040
+ {
1041
+ return leaf1().all_bits_set<x86_cpuid_leaf1::ecx::osxsave>();
1042
+ }
1043
+
1044
+ namespace detail
1045
+ {
1046
+ #if XSIMD_TARGET_X86
1047
+
1048
+ inline cpuid_reg_t x86_cpuid(int leaf, int subleaf) noexcept
1049
+ {
1050
+ cpuid_reg_t reg = {};
1051
+ #if defined(_MSC_VER)
1052
+ int buf[4];
1053
+ __cpuidex(buf, leaf, subleaf);
1054
+ std::memcpy(reg.data(), buf, sizeof(buf));
1055
+
1056
+ // Intel compiler has long had support for `__cpuid`, but only recently for `__cpuidex`.
1057
+ // Modern Clang and GCC also now support `__cpuidex`.
1058
+ // It was decided to keep the inline ASM version for maximum compatibility, as the difference
1059
+ // in ASM is negligible compared to the cost of CPUID.
1060
+ // https://github.com/xtensor-stack/xsimd/pull/1278
1061
+ #elif XSIMD_WITH_INLINE_ASM
1062
+
1063
+ #if defined(__i386__) && defined(__PIC__)
1064
+ // %ebx may be the PIC register
1065
+ __asm__("xchg{l}\t{%%}ebx, %1\n\t"
1066
+ "cpuid\n\t"
1067
+ "xchg{l}\t{%%}ebx, %1\n\t"
1068
+ : "=a"(reg[0]), "=r"(reg[1]), "=c"(reg[2]), "=d"(reg[3])
1069
+ : "0"(leaf), "2"(subleaf));
1070
+
1071
+ #else
1072
+ __asm__("cpuid\n\t"
1073
+ : "=a"(reg[0]), "=b"(reg[1]), "=c"(reg[2]), "=d"(reg[3])
1074
+ : "0"(leaf), "2"(subleaf));
1075
+ #endif
1076
+ #endif
1077
+ return reg;
1078
+ }
1079
+
1080
+ inline x86_reg32_t x86_xcr0_low() noexcept
1081
+ {
1082
+ #if defined(_MSC_VER)
1083
+ #if _MSC_VER >= 1400
1084
+ return static_cast<x86_reg32_t>(_xgetbv(0));
1085
+ #else
1086
+ #error "_MSC_VER < 1400 is not supported"
1087
+ #endif
1088
+
1089
+ #elif XSIMD_WITH_INLINE_ASM
1090
+ x86_reg32_t xcr0 = {};
1091
+ __asm__(
1092
+ "xorl %%ecx, %%ecx\n"
1093
+ "xgetbv\n"
1094
+ : "=a"(xcr0)
1095
+ :
1096
+ #if defined(__i386__)
1097
+ : "ecx", "edx"
1098
+ #else
1099
+ : "rcx", "rdx"
1100
+ #endif
1101
+ );
1102
+ return xcr0;
1103
+ #endif
1104
+ }
1105
+
1106
+ #else // XSIMD_TARGET_X86
1107
+
1108
+ inline cpuid_reg_t x86_cpuid(int /* leaf */, int /* subleaf */) noexcept
1109
+ {
1110
+ return {}; // All bits to zero
1111
+ }
1112
+
1113
+ inline x86_reg32_t x86_xcr0_low() noexcept
1114
+ {
1115
+ return {}; // All bits to zero
1116
+ }
1117
+
1118
+ #endif // XSIMD_TARGET_X86
1119
+ }
1120
+ }
1121
+ #endif