cranelift_codegen_meta/isa/
x86.rs

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