1{ lib }:
2
3rec {
4 # gcc.arch to its features (as in /proc/cpuinfo)
5 features = {
6 # x86_64 Generic
7 # Spec: https://gitlab.com/x86-psABIs/x86-64-ABI/
8 default = [ ];
9 x86-64 = [ ];
10 x86-64-v2 = [ "sse3" "ssse3" "sse4_1" "sse4_2" ];
11 x86-64-v3 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "avx" "avx2" "fma" ];
12 x86-64-v4 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "avx" "avx2" "avx512" "fma" ];
13 # x86_64 Intel
14 nehalem = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" ];
15 westmere = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" ];
16 sandybridge = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
17 ivybridge = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
18 haswell = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
19 broadwell = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
20 skylake = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
21 skylake-avx512 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "avx512" "fma" ];
22 cannonlake = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "avx512" "fma" ];
23 icelake-client = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "avx512" "fma" ];
24 icelake-server = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "avx512" "fma" ];
25 cascadelake = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "avx512" "fma" ];
26 cooperlake = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "avx512" "fma" ];
27 tigerlake = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "avx512" "fma" ];
28 alderlake = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
29 # x86_64 AMD
30 btver1 = [ "sse3" "ssse3" "sse4_1" "sse4_2" ];
31 btver2 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
32 bdver1 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "fma" "fma4" ];
33 bdver2 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "fma" "fma4" ];
34 bdver3 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "fma" "fma4" ];
35 bdver4 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "fma" "fma4" ];
36 znver1 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "fma" ];
37 znver2 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "fma" ];
38 znver3 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "fma" ];
39 znver4 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "avx512" "fma" ];
40 # other
41 armv5te = [ ];
42 armv6 = [ ];
43 armv7-a = [ ];
44 armv8-a = [ ];
45 mips32 = [ ];
46 loongson2f = [ ];
47 };
48
49 # a superior CPU has all the features of an inferior and is able to build and test code for it
50 inferiors = {
51 # x86_64 Generic
52 default = [ ];
53 x86-64 = [ ];
54 x86-64-v2 = [ "x86-64" ];
55 x86-64-v3 = [ "x86-64-v2" ] ++ inferiors.x86-64-v2;
56 x86-64-v4 = [ "x86-64-v3" ] ++ inferiors.x86-64-v3;
57
58 # x86_64 Intel
59 # https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
60 nehalem = [ "x86-64-v2" ] ++ inferiors.x86-64-v2;
61 westmere = [ "nehalem" ] ++ inferiors.nehalem;
62 sandybridge = [ "westmere" ] ++ inferiors.westmere;
63 ivybridge = [ "sandybridge" ] ++ inferiors.sandybridge;
64
65 haswell = lib.unique ([ "ivybridge" "x86-64-v3" ] ++ inferiors.ivybridge ++ inferiors.x86-64-v3);
66 broadwell = [ "haswell" ] ++ inferiors.haswell;
67 skylake = [ "broadwell" ] ++ inferiors.broadwell;
68
69 skylake-avx512 = lib.unique ([ "skylake" "x86-64-v4" ] ++ inferiors.skylake ++ inferiors.x86-64-v4);
70 cannonlake = [ "skylake-avx512" ] ++ inferiors.skylake-avx512;
71 icelake-client = [ "cannonlake" ] ++ inferiors.cannonlake;
72 icelake-server = [ "icelake-client" ] ++ inferiors.icelake-client;
73 cascadelake = [ "cannonlake" ] ++ inferiors.cannonlake;
74 cooperlake = [ "cascadelake" ] ++ inferiors.cascadelake;
75 tigerlake = [ "icelake-server" ] ++ inferiors.icelake-server;
76
77 # CX16 does not exist on alderlake, while it does on nearly all other intel CPUs
78 alderlake = [ ];
79
80 # x86_64 AMD
81 # TODO: fill this (need testing)
82 btver1 = [ ];
83 btver2 = [ ];
84 bdver1 = [ ];
85 bdver2 = [ ];
86 bdver3 = [ ];
87 bdver4 = [ ];
88 # Regarding `skylake` as inferior of `znver1`, there are reports of
89 # successful usage by Gentoo users and Phoronix benchmarking of different
90 # `-march` targets.
91 #
92 # The GCC documentation on extensions used and wikichip documentation
93 # regarding supperted extensions on znver1 and skylake was used to create
94 # this partial order.
95 #
96 # Note:
97 #
98 # - The successors of `skylake` (`cannonlake`, `icelake`, etc) use `avx512`
99 # which no current AMD Zen michroarch support.
100 # - `znver1` uses `ABM`, `CLZERO`, `CX16`, `MWAITX`, and `SSE4A` which no
101 # current Intel microarch support.
102 #
103 # https://www.phoronix.com/scan.php?page=article&item=amd-znver3-gcc11&num=1
104 # https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
105 # https://en.wikichip.org/wiki/amd/microarchitectures/zen
106 # https://en.wikichip.org/wiki/intel/microarchitectures/skylake
107 znver1 = [ "skylake" ] ++ inferiors.skylake; # Includes haswell and x86-64-v3
108 znver2 = [ "znver1" ] ++ inferiors.znver1;
109 znver3 = [ "znver2" ] ++ inferiors.znver2;
110 znver4 = lib.unique ([ "znver3" "x86-64-v4" ] ++ inferiors.znver3 ++ inferiors.x86-64-v4);
111
112 # other
113 armv5te = [ ];
114 armv6 = [ ];
115 armv7-a = [ ];
116 armv8-a = [ ];
117 mips32 = [ ];
118 loongson2f = [ ];
119 };
120
121 predicates = let
122 featureSupport = feature: x: builtins.elem feature features.${x} or [];
123 in {
124 sse3Support = featureSupport "sse3";
125 ssse3Support = featureSupport "ssse3";
126 sse4_1Support = featureSupport "sse4_1";
127 sse4_2Support = featureSupport "sse4_2";
128 sse4_aSupport = featureSupport "sse4a";
129 avxSupport = featureSupport "avx";
130 avx2Support = featureSupport "avx2";
131 avx512Support = featureSupport "avx512";
132 aesSupport = featureSupport "aes";
133 fmaSupport = featureSupport "fma";
134 fma4Support = featureSupport "fma4";
135 };
136}