Skip to main content

cranelift_codegen_meta/isa/
x86.rs

1use crate::cdsl::isa::TargetIsa;
2use crate::cdsl::settings::SettingGroupBuilder;
3
4pub(crate) fn define() -> TargetIsa {
5    let mut settings = SettingGroupBuilder::new("x86");
6
7    // CPUID.01H:ECX
8    let has_sse3 = settings.add_bool(
9        "has_sse3",
10        "Has support for SSE3.",
11        "SSE3: CPUID.01H:ECX.SSE3[bit 0]",
12        false,
13    );
14    let has_ssse3 = settings.add_bool(
15        "has_ssse3",
16        "Has support for SSSE3.",
17        "SSSE3: CPUID.01H:ECX.SSSE3[bit 9]",
18        false,
19    );
20    let has_cmpxchg16b = settings.add_bool(
21        "has_cmpxchg16b",
22        "Has support for CMPXCHG16b.",
23        "CMPXCHG16b: CPUID.01H:ECX.CMPXCHG16B[bit 13]",
24        false,
25    );
26    let has_sse41 = settings.add_bool(
27        "has_sse41",
28        "Has support for SSE4.1.",
29        "SSE4.1: CPUID.01H:ECX.SSE4_1[bit 19]",
30        false,
31    );
32    let has_sse42 = settings.add_bool(
33        "has_sse42",
34        "Has support for SSE4.2.",
35        "SSE4.2: CPUID.01H:ECX.SSE4_2[bit 20]",
36        false,
37    );
38    let has_avx = settings.add_bool(
39        "has_avx",
40        "Has support for AVX.",
41        "AVX: CPUID.01H:ECX.AVX[bit 28]",
42        false,
43    );
44    let has_avx2 = settings.add_bool(
45        "has_avx2",
46        "Has support for AVX2.",
47        "AVX2: CPUID.07H:EBX.AVX2[bit 5]",
48        false,
49    );
50    let has_fma = settings.add_bool(
51        "has_fma",
52        "Has support for FMA.",
53        "FMA: CPUID.01H:ECX.FMA[bit 12]",
54        false,
55    );
56    let has_avx_vnni = settings.add_bool(
57        "has_avx_vnni",
58        "Has support for AVX-VNNI.",
59        "AVX-VNNI: CPUID.07H.01H:EAX.AVX_VNNI[bit 4]",
60        false,
61    );
62    let has_avx512bitalg = settings.add_bool(
63        "has_avx512bitalg",
64        "Has support for AVX512BITALG.",
65        "AVX512BITALG: CPUID.07H:ECX.AVX512BITALG[bit 12]",
66        false,
67    );
68    let has_avx512dq = settings.add_bool(
69        "has_avx512dq",
70        "Has support for AVX512DQ.",
71        "AVX512DQ: CPUID.07H:EBX.AVX512DQ[bit 17]",
72        false,
73    );
74    let has_avx512vl = settings.add_bool(
75        "has_avx512vl",
76        "Has support for AVX512VL.",
77        "AVX512VL: CPUID.07H:EBX.AVX512VL[bit 31]",
78        false,
79    );
80    let has_avx512vbmi = settings.add_bool(
81        "has_avx512vbmi",
82        "Has support for AVX512VMBI.",
83        "AVX512VBMI: CPUID.07H:ECX.AVX512VBMI[bit 1]",
84        false,
85    );
86    let has_avx512f = settings.add_bool(
87        "has_avx512f",
88        "Has support for AVX512F.",
89        "AVX512F: CPUID.07H:EBX.AVX512F[bit 16]",
90        false,
91    );
92    let has_avx512vnni = settings.add_bool(
93        "has_avx512vnni",
94        "Has support for AVX512VNNI.",
95        "AVX512VNNI: CPUID.07H:ECX.AVX512_VNNI[bit 11]",
96        false,
97    );
98    let has_popcnt = settings.add_bool(
99        "has_popcnt",
100        "Has support for POPCNT.",
101        "POPCNT: CPUID.01H:ECX.POPCNT[bit 23]",
102        false,
103    );
104
105    // CPUID.(EAX=07H, ECX=0H):EBX
106    let has_bmi1 = settings.add_bool(
107        "has_bmi1",
108        "Has support for BMI1.",
109        "BMI1: CPUID.(EAX=07H, ECX=0H):EBX.BMI1[bit 3]",
110        false,
111    );
112    let has_bmi2 = settings.add_bool(
113        "has_bmi2",
114        "Has support for BMI2.",
115        "BMI2: CPUID.(EAX=07H, ECX=0H):EBX.BMI2[bit 8]",
116        false,
117    );
118
119    // CPUID.EAX=80000001H:ECX
120    let has_lzcnt = settings.add_bool(
121        "has_lzcnt",
122        "Has support for LZCNT.",
123        "LZCNT: CPUID.EAX=80000001H:ECX.LZCNT[bit 5]",
124        false,
125    );
126
127    let sse3 = settings.add_preset("sse3", "SSE3 and earlier.", preset!(has_sse3));
128    let ssse3 = settings.add_preset("ssse3", "SSSE3 and earlier.", preset!(sse3 && has_ssse3));
129    let sse41 = settings.add_preset("sse41", "SSE4.1 and earlier.", preset!(ssse3 && has_sse41));
130    let sse42 = settings.add_preset("sse42", "SSE4.2 and earlier.", preset!(sse41 && has_sse42));
131
132    // Presets corresponding to x86 CPUs.
133    // Features and architecture names are from LLVM's x86 presets:
134    // https://github.com/llvm/llvm-project/blob/d4493dd1ed58ac3f1eab0c4ca6e363e2b15bfd1c/llvm/lib/Target/X86/X86.td#L1300-L1643
135    settings.add_preset(
136        "baseline",
137        "A baseline preset with no extensions enabled.",
138        preset!(),
139    );
140
141    // Intel CPUs
142
143    // Netburst
144    settings.add_preset(
145        "nocona",
146        "Nocona microarchitecture.",
147        preset!(sse3 && has_cmpxchg16b),
148    );
149
150    // Intel Core 2 Solo/Duo
151    settings.add_preset(
152        "core2",
153        "Core 2 microarchitecture.",
154        preset!(sse3 && has_cmpxchg16b),
155    );
156    settings.add_preset(
157        "penryn",
158        "Penryn microarchitecture.",
159        preset!(sse41 && has_cmpxchg16b),
160    );
161
162    // Intel Atom CPUs
163    let atom = settings.add_preset(
164        "atom",
165        "Atom microarchitecture.",
166        preset!(ssse3 && has_cmpxchg16b),
167    );
168    settings.add_preset("bonnell", "Bonnell microarchitecture.", preset!(atom));
169    let silvermont = settings.add_preset(
170        "silvermont",
171        "Silvermont microarchitecture.",
172        preset!(atom && sse42 && has_popcnt),
173    );
174    settings.add_preset("slm", "Silvermont microarchitecture.", preset!(silvermont));
175    let goldmont = settings.add_preset(
176        "goldmont",
177        "Goldmont microarchitecture.",
178        preset!(silvermont),
179    );
180    settings.add_preset(
181        "goldmont-plus",
182        "Goldmont Plus microarchitecture.",
183        preset!(goldmont),
184    );
185    let tremont = settings.add_preset("tremont", "Tremont microarchitecture.", preset!(goldmont));
186
187    let alderlake = settings.add_preset(
188        "alderlake",
189        "Alderlake microarchitecture.",
190        preset!(tremont && has_bmi1 && has_bmi2 && has_lzcnt && has_fma && has_avx_vnni),
191    );
192    let sierra_forest = settings.add_preset(
193        "sierraforest",
194        "Sierra Forest microarchitecture.",
195        preset!(alderlake),
196    );
197    settings.add_preset(
198        "grandridge",
199        "Grandridge microarchitecture.",
200        preset!(sierra_forest),
201    );
202    let nehalem = settings.add_preset(
203        "nehalem",
204        "Nehalem microarchitecture.",
205        preset!(sse42 && has_popcnt && has_cmpxchg16b),
206    );
207    settings.add_preset("corei7", "Core i7 microarchitecture.", preset!(nehalem));
208    let westmere = settings.add_preset("westmere", "Westmere microarchitecture.", preset!(nehalem));
209    let sandy_bridge = settings.add_preset(
210        "sandybridge",
211        "Sandy Bridge microarchitecture.",
212        preset!(westmere && has_avx),
213    );
214    settings.add_preset(
215        "corei7-avx",
216        "Core i7 AVX microarchitecture.",
217        preset!(sandy_bridge),
218    );
219    let ivy_bridge = settings.add_preset(
220        "ivybridge",
221        "Ivy Bridge microarchitecture.",
222        preset!(sandy_bridge),
223    );
224    settings.add_preset(
225        "core-avx-i",
226        "Intel Core CPU with 64-bit extensions.",
227        preset!(ivy_bridge),
228    );
229    let haswell = settings.add_preset(
230        "haswell",
231        "Haswell microarchitecture.",
232        preset!(ivy_bridge && has_avx2 && has_bmi1 && has_bmi2 && has_fma && has_lzcnt),
233    );
234    settings.add_preset(
235        "core-avx2",
236        "Intel Core CPU with AVX2 extensions.",
237        preset!(haswell),
238    );
239    let broadwell = settings.add_preset(
240        "broadwell",
241        "Broadwell microarchitecture.",
242        preset!(haswell),
243    );
244    let skylake = settings.add_preset("skylake", "Skylake microarchitecture.", preset!(broadwell));
245    let knights_landing = settings.add_preset(
246        "knl",
247        "Knights Landing microarchitecture.",
248        preset!(
249            has_popcnt
250                && has_avx512f
251                && has_fma
252                && has_bmi1
253                && has_bmi2
254                && has_lzcnt
255                && has_cmpxchg16b
256        ),
257    );
258    settings.add_preset(
259        "knm",
260        "Knights Mill microarchitecture.",
261        preset!(knights_landing),
262    );
263    let skylake_avx512 = settings.add_preset(
264        "skylake-avx512",
265        "Skylake AVX512 microarchitecture.",
266        preset!(broadwell && has_avx512f && has_avx512dq && has_avx512vl),
267    );
268    settings.add_preset(
269        "skx",
270        "Skylake AVX512 microarchitecture.",
271        preset!(skylake_avx512),
272    );
273    let cascadelake = settings.add_preset(
274        "cascadelake",
275        "Cascade Lake microarchitecture.",
276        preset!(skylake_avx512 && has_avx512vnni),
277    );
278    settings.add_preset(
279        "cooperlake",
280        "Cooper Lake microarchitecture.",
281        preset!(cascadelake),
282    );
283    let cannonlake = settings.add_preset(
284        "cannonlake",
285        "Canon Lake microarchitecture.",
286        preset!(skylake && has_avx512f && has_avx512dq && has_avx512vl && has_avx512vbmi),
287    );
288    let icelake_client = settings.add_preset(
289        "icelake-client",
290        "Ice Lake microarchitecture.",
291        preset!(cannonlake && has_avx512bitalg && has_avx512vnni),
292    );
293    // LLVM doesn't use the name "icelake" but Cranelift did in the past; alias it
294    settings.add_preset(
295        "icelake",
296        "Ice Lake microarchitecture",
297        preset!(icelake_client),
298    );
299    let icelake_server = settings.add_preset(
300        "icelake-server",
301        "Ice Lake (server) microarchitecture.",
302        preset!(icelake_client),
303    );
304    settings.add_preset(
305        "tigerlake",
306        "Tiger Lake microarchitecture.",
307        preset!(icelake_client),
308    );
309    let sapphire_rapids = settings.add_preset(
310        "sapphirerapids",
311        "Sapphire Rapids microarchitecture.",
312        preset!(icelake_server),
313    );
314    settings.add_preset(
315        "raptorlake",
316        "Raptor Lake microarchitecture.",
317        preset!(alderlake),
318    );
319    settings.add_preset(
320        "meteorlake",
321        "Meteor Lake microarchitecture.",
322        preset!(alderlake),
323    );
324    settings.add_preset(
325        "graniterapids",
326        "Granite Rapids microarchitecture.",
327        preset!(sapphire_rapids),
328    );
329
330    // AMD CPUs
331
332    settings.add_preset("opteron", "Opteron microarchitecture.", preset!());
333    settings.add_preset("k8", "K8 Hammer microarchitecture.", preset!());
334    settings.add_preset("athlon64", "Athlon64 microarchitecture.", preset!());
335    settings.add_preset("athlon-fx", "Athlon FX microarchitecture.", preset!());
336    settings.add_preset(
337        "opteron-sse3",
338        "Opteron microarchitecture with support for SSE3 instructions.",
339        preset!(sse3 && has_cmpxchg16b),
340    );
341    settings.add_preset(
342        "k8-sse3",
343        "K8 Hammer microarchitecture with support for SSE3 instructions.",
344        preset!(sse3 && has_cmpxchg16b),
345    );
346    settings.add_preset(
347        "athlon64-sse3",
348        "Athlon 64 microarchitecture with support for SSE3 instructions.",
349        preset!(sse3 && has_cmpxchg16b),
350    );
351    let barcelona = settings.add_preset(
352        "barcelona",
353        "Barcelona microarchitecture.",
354        preset!(has_popcnt && has_lzcnt && has_cmpxchg16b),
355    );
356    settings.add_preset(
357        "amdfam10",
358        "AMD Family 10h microarchitecture",
359        preset!(barcelona),
360    );
361
362    let btver1 = settings.add_preset(
363        "btver1",
364        "Bobcat microarchitecture.",
365        preset!(ssse3 && has_lzcnt && has_popcnt && has_cmpxchg16b),
366    );
367    settings.add_preset(
368        "btver2",
369        "Jaguar microarchitecture.",
370        preset!(btver1 && has_avx && has_bmi1),
371    );
372
373    let bdver1 = settings.add_preset(
374        "bdver1",
375        "Bulldozer microarchitecture",
376        preset!(has_lzcnt && has_popcnt && ssse3 && has_cmpxchg16b),
377    );
378    let bdver2 = settings.add_preset(
379        "bdver2",
380        "Piledriver microarchitecture.",
381        preset!(bdver1 && has_bmi1),
382    );
383    let bdver3 = settings.add_preset("bdver3", "Steamroller microarchitecture.", preset!(bdver2));
384    settings.add_preset(
385        "bdver4",
386        "Excavator microarchitecture.",
387        preset!(bdver3 && has_avx2 && has_bmi2),
388    );
389
390    let znver1 = settings.add_preset(
391        "znver1",
392        "Zen (first generation) microarchitecture.",
393        preset!(
394            sse42 && has_popcnt && has_bmi1 && has_bmi2 && has_lzcnt && has_fma && has_cmpxchg16b
395        ),
396    );
397    let znver2 = settings.add_preset(
398        "znver2",
399        "Zen (second generation) microarchitecture.",
400        preset!(znver1),
401    );
402    let znver3 = settings.add_preset(
403        "znver3",
404        "Zen (third generation) microarchitecture.",
405        preset!(znver2),
406    );
407    settings.add_preset(
408        "znver4",
409        "Zen (fourth generation) microarchitecture.",
410        preset!(
411            znver3
412                && has_avx512bitalg
413                && has_avx512dq
414                && has_avx512f
415                && has_avx512vbmi
416                && has_avx512vl
417        ),
418    );
419
420    // Generic
421
422    settings.add_preset("x86-64", "Generic x86-64 microarchitecture.", preset!());
423    let x86_64_v2 = settings.add_preset(
424        "x86-64-v2",
425        "Generic x86-64 (V2) microarchitecture.",
426        preset!(sse42 && has_popcnt && has_cmpxchg16b),
427    );
428    let x86_64_v3 = settings.add_preset(
429        "x86-64-v3",
430        "Generic x86-64 (V3) microarchitecture.",
431        preset!(x86_64_v2 && has_bmi1 && has_bmi2 && has_fma && has_lzcnt && has_avx2),
432    );
433    settings.add_preset(
434        "x86-64-v4",
435        "Generic x86-64 (V4) microarchitecture.",
436        preset!(x86_64_v3 && has_avx512dq && has_avx512vl),
437    );
438
439    TargetIsa::new("x86", settings.build())
440}