1 use crate::cdsl::isa::TargetIsa;
2 use crate::cdsl::settings::{PredicateNode, SettingGroupBuilder};
3 
4 pub(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 }
449