@@ -7,6 +7,74 @@ export AbstractPlatform, Platform, HostPlatform, platform_dlext, tags, arch, os,
7
7
select_platform, platforms_match, platform_name
8
8
import . Libc. Libdl
9
9
10
+ # ## Submodule with information about CPU features
11
+ module CPUID
12
+
13
+ export cpu_isa
14
+
15
+ """
16
+ ISA(features::Set{UInt32})
17
+
18
+ A structure which represents the Instruction Set Architecture (ISA) of a
19
+ computer. It holds the `Set` of features of the CPU.
20
+
21
+ The numerical values of the features are automatically generated from the C
22
+ source code of Julia and stored in the `features_h.jl` Julia file.
23
+ """
24
+ struct ISA
25
+ features:: Set{UInt32}
26
+ end
27
+
28
+ Base.:<= (a:: ISA , b:: ISA ) = a. features <= b. features
29
+ Base.:< (a:: ISA , b:: ISA ) = a. features < b. features
30
+ Base. isless (a:: ISA , b:: ISA ) = a < b
31
+
32
+ include (" features_h.jl" )
33
+
34
+ # Keep in sync with `arch_march_isa_mapping`.
35
+ const ISAs_by_family = Dict (
36
+ " x86_64" => (
37
+ # Source: https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html.
38
+ # Implicit in all sets, because always required: mmx, sse, sse2
39
+ " x86_64" => ISA (Set {UInt32} ()),
40
+ " core2" => ISA (Set ((JL_X86_sse3, JL_X86_ssse3))),
41
+ " nehalem" => ISA (Set ((JL_X86_sse3, JL_X86_ssse3, JL_X86_sse41, JL_X86_sse42, JL_X86_popcnt))),
42
+ " sandybridge" => ISA (Set ((JL_X86_sse3, JL_X86_ssse3, JL_X86_sse41, JL_X86_sse42, JL_X86_popcnt, JL_X86_avx, JL_X86_aes, JL_X86_pclmul))),
43
+ " haswell" => ISA (Set ((JL_X86_movbe, JL_X86_sse3, JL_X86_ssse3, JL_X86_sse41, JL_X86_sse42, JL_X86_popcnt, JL_X86_avx, JL_X86_avx2, JL_X86_aes, JL_X86_pclmul, JL_X86_fsgsbase, JL_X86_rdrnd, JL_X86_fma, JL_X86_bmi, JL_X86_bmi2, JL_X86_f16c))),
44
+ " skylake" => ISA (Set ((JL_X86_movbe, JL_X86_sse3, JL_X86_ssse3, JL_X86_sse41, JL_X86_sse42, JL_X86_popcnt, JL_X86_avx, JL_X86_avx2, JL_X86_aes, JL_X86_pclmul, JL_X86_fsgsbase, JL_X86_rdrnd, JL_X86_fma, JL_X86_bmi, JL_X86_bmi2, JL_X86_f16c, JL_X86_rdseed, JL_X86_adx, JL_X86_prfchw, JL_X86_clflushopt, JL_X86_xsavec, JL_X86_xsaves))),
45
+ " skylake_avx512" => ISA (Set ((JL_X86_movbe, JL_X86_sse3, JL_X86_ssse3, JL_X86_sse41, JL_X86_sse42, JL_X86_popcnt, JL_X86_pku, JL_X86_avx, JL_X86_avx2, JL_X86_aes, JL_X86_pclmul, JL_X86_fsgsbase, JL_X86_rdrnd, JL_X86_fma, JL_X86_bmi, JL_X86_bmi2, JL_X86_f16c, JL_X86_rdseed, JL_X86_adx, JL_X86_prfchw, JL_X86_clflushopt, JL_X86_xsavec, JL_X86_xsaves, JL_X86_avx512f, JL_X86_clwb, JL_X86_avx512vl, JL_X86_avx512bw, JL_X86_avx512dq, JL_X86_avx512cd))),
46
+ ),
47
+ " arm" => (
48
+ " armv7l" => ISA (Set {UInt32} ()),
49
+ " armv7l_neon" => ISA (Set ((JL_AArch32_neon,))),
50
+ " armv7l_neon_vfp4" => ISA (Set ((JL_AArch32_neon, JL_AArch32_vfp4))),
51
+ ),
52
+ " aarch64" => (
53
+ # Implicit in all sets, because always required: fp, asimd
54
+ " armv8.0_a" => ISA (Set {UInt32} ()),
55
+ " armv8.1_a" => ISA (Set ((JL_AArch64_lse, JL_AArch64_crc, JL_AArch64_rdm))),
56
+ " armv8.2_a_crypto" => ISA (Set ((JL_AArch64_lse, JL_AArch64_crc, JL_AArch64_rdm, JL_AArch64_aes, JL_AArch64_sha2))),
57
+ " armv8.4_a_crypto_sve" => ISA (Set ((JL_AArch64_lse, JL_AArch64_crc, JL_AArch64_rdm, JL_AArch64_fp16fml, JL_AArch64_dotprod, JL_AArch64_aes, JL_AArch64_sha2, JL_AArch64_dotprod, JL_AArch64_sve))),
58
+ ),
59
+ )
60
+
61
+ test_cpu_feature (feature:: UInt32 ) = ccall (:jl_test_cpu_feature , Bool, (UInt32,), feature)
62
+ cpu_family () = String (Sys. ARCH)
63
+
64
+ """
65
+ cpu_isa()
66
+
67
+ Return the [`ISA`](@ref) (instruction set architecture) of the current CPU.
68
+ """
69
+ function cpu_isa ()
70
+ all_features = last (last (get (ISAs_by_family, cpu_family (), " " => [ISA (Set {UInt32} ())]))). features
71
+ return ISA (Set {UInt32} (feat for feat in all_features if test_cpu_feature (feat)))
72
+ end
73
+
74
+ end # module CPUID
75
+
76
+ using . CPUID
77
+
10
78
# This exists to ease compatibility with old-style Platform objects
11
79
abstract type AbstractPlatform; end
12
80
@@ -567,6 +635,31 @@ const arch_mapping = Dict(
567
635
" armv6l" => " armv6l" ,
568
636
" powerpc64le" => " p(ower)?pc64le" ,
569
637
)
638
+ # Keep this in sync with `CPUID.ISAs_by_family`
639
+ const arch_march_isa_mapping = let
640
+ function get_set (arch, name)
641
+ all = CPUID. ISAs_by_family[arch]
642
+ return all[findfirst (x -> x. first == name, all)]. second
643
+ end
644
+ Dict (
645
+ " x86_64" => Dict {String,CPUID.ISA} (
646
+ " x86_64" => get_set (" x86_64" , " x86_64" ),
647
+ " avx" => get_set (" x86_64" , " sandybridge" ),
648
+ " avx2" => get_set (" x86_64" , " haswell" ),
649
+ " avx512" => get_set (" x86_64" , " skylake_avx512" ),
650
+ ),
651
+ " armv7l" => Dict {String,CPUID.ISA} (
652
+ " armv7l" => get_set (" arm" , " armv7l" ),
653
+ " neon" => get_set (" arm" , " armv7l_neon" ),
654
+ " vfp4" => get_set (" arm" , " armv7l_neon_vfp4" ),
655
+ ),
656
+ " aarch64" => Dict {String,CPUID.ISA} (
657
+ " armv8" => get_set (" aarch64" , " armv8.0_a" ),
658
+ " thunderx2" => get_set (" aarch64" , " armv8.1_a" ),
659
+ " carmel" => get_set (" aarch64" , " armv8.2_a_crypto" ),
660
+ ),
661
+ )
662
+ end
570
663
const os_mapping = Dict (
571
664
" macos" => " -apple-darwin[\\ d\\ .]*" ,
572
665
" freebsd" => " -(.*-)?freebsd[\\ d\\ .]*" ,
0 commit comments