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