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