1 | //===--- X86.cpp - Implement X86 target feature support -------------------===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements X86 TargetInfo objects. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "X86.h" |
14 | #include "clang/Basic/Builtins.h" |
15 | #include "clang/Basic/Diagnostic.h" |
16 | #include "clang/Basic/TargetBuiltins.h" |
17 | #include "llvm/ADT/StringRef.h" |
18 | #include "llvm/ADT/StringSwitch.h" |
19 | #include "llvm/TargetParser/X86TargetParser.h" |
20 | #include <optional> |
21 | |
22 | namespace clang { |
23 | namespace targets { |
24 | |
25 | // The x86-32 builtins are a subset and prefix of the x86-64 builtins. |
26 | static constexpr int NumX86Builtins = |
27 | X86::LastX86CommonBuiltin - Builtin::FirstTSBuiltin + 1; |
28 | static constexpr int NumX86_64Builtins = |
29 | X86::LastTSBuiltin - X86::FirstX86_64Builtin; |
30 | static constexpr int NumBuiltins = X86::LastTSBuiltin - Builtin::FirstTSBuiltin; |
31 | static_assert(NumBuiltins == (NumX86Builtins + NumX86_64Builtins)); |
32 | |
33 | namespace X86 { |
34 | #define GET_BUILTIN_STR_TABLE |
35 | #include "clang/Basic/BuiltinsX86.inc" |
36 | #undef GET_BUILTIN_STR_TABLE |
37 | |
38 | static constexpr Builtin::Info BuiltinInfos[] = { |
39 | #define GET_BUILTIN_INFOS |
40 | #include "clang/Basic/BuiltinsX86.inc" |
41 | #undef GET_BUILTIN_INFOS |
42 | }; |
43 | |
44 | static constexpr Builtin::Info PrefixedBuiltinInfos[] = { |
45 | #define GET_BUILTIN_PREFIXED_INFOS |
46 | #include "clang/Basic/BuiltinsX86.inc" |
47 | #undef GET_BUILTIN_PREFIXED_INFOS |
48 | }; |
49 | static_assert((std::size(BuiltinInfos) + std::size(PrefixedBuiltinInfos)) == |
50 | NumX86Builtins); |
51 | } // namespace X86 |
52 | |
53 | namespace X86_64 { |
54 | #define GET_BUILTIN_STR_TABLE |
55 | #include "clang/Basic/BuiltinsX86_64.inc" |
56 | #undef GET_BUILTIN_STR_TABLE |
57 | |
58 | static constexpr Builtin::Info BuiltinInfos[] = { |
59 | #define GET_BUILTIN_INFOS |
60 | #include "clang/Basic/BuiltinsX86_64.inc" |
61 | #undef GET_BUILTIN_INFOS |
62 | }; |
63 | |
64 | static constexpr Builtin::Info PrefixedBuiltinInfos[] = { |
65 | #define GET_BUILTIN_PREFIXED_INFOS |
66 | #include "clang/Basic/BuiltinsX86_64.inc" |
67 | #undef GET_BUILTIN_PREFIXED_INFOS |
68 | }; |
69 | static_assert((std::size(BuiltinInfos) + std::size(PrefixedBuiltinInfos)) == |
70 | NumX86_64Builtins); |
71 | } // namespace X86_64 |
72 | |
73 | static const char *const GCCRegNames[] = { |
74 | "ax", "dx", "cx", "bx", "si", "di", "bp", "sp", |
75 | "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)", |
76 | "argp", "flags", "fpcr", "fpsr", "dirflag", "frame", "xmm0", "xmm1", |
77 | "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "mm0", "mm1", |
78 | "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", "r8", "r9", |
79 | "r10", "r11", "r12", "r13", "r14", "r15", "xmm8", "xmm9", |
80 | "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "ymm0", "ymm1", |
81 | "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", |
82 | "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", "xmm16", "xmm17", |
83 | "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23", "xmm24", "xmm25", |
84 | "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31", "ymm16", "ymm17", |
85 | "ymm18", "ymm19", "ymm20", "ymm21", "ymm22", "ymm23", "ymm24", "ymm25", |
86 | "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31", "zmm0", "zmm1", |
87 | "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", |
88 | "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", |
89 | "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", |
90 | "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "k0", "k1", |
91 | "k2", "k3", "k4", "k5", "k6", "k7", |
92 | "cr0", "cr2", "cr3", "cr4", "cr8", |
93 | "dr0", "dr1", "dr2", "dr3", "dr6", "dr7", |
94 | "bnd0", "bnd1", "bnd2", "bnd3", |
95 | "tmm0", "tmm1", "tmm2", "tmm3", "tmm4", "tmm5", "tmm6", "tmm7", |
96 | "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", |
97 | "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", |
98 | }; |
99 | |
100 | const TargetInfo::AddlRegName AddlRegNames[] = { |
101 | {.Names: {"al", "ah", "eax", "rax"}, .RegNum: 0}, |
102 | {.Names: {"bl", "bh", "ebx", "rbx"}, .RegNum: 3}, |
103 | {.Names: {"cl", "ch", "ecx", "rcx"}, .RegNum: 2}, |
104 | {.Names: {"dl", "dh", "edx", "rdx"}, .RegNum: 1}, |
105 | {.Names: {"esi", "rsi"}, .RegNum: 4}, |
106 | {.Names: {"edi", "rdi"}, .RegNum: 5}, |
107 | {.Names: {"esp", "rsp"}, .RegNum: 7}, |
108 | {.Names: {"ebp", "rbp"}, .RegNum: 6}, |
109 | {.Names: {"r8d", "r8w", "r8b"}, .RegNum: 38}, |
110 | {.Names: {"r9d", "r9w", "r9b"}, .RegNum: 39}, |
111 | {.Names: {"r10d", "r10w", "r10b"}, .RegNum: 40}, |
112 | {.Names: {"r11d", "r11w", "r11b"}, .RegNum: 41}, |
113 | {.Names: {"r12d", "r12w", "r12b"}, .RegNum: 42}, |
114 | {.Names: {"r13d", "r13w", "r13b"}, .RegNum: 43}, |
115 | {.Names: {"r14d", "r14w", "r14b"}, .RegNum: 44}, |
116 | {.Names: {"r15d", "r15w", "r15b"}, .RegNum: 45}, |
117 | {.Names: {"r16d", "r16w", "r16b"}, .RegNum: 165}, |
118 | {.Names: {"r17d", "r17w", "r17b"}, .RegNum: 166}, |
119 | {.Names: {"r18d", "r18w", "r18b"}, .RegNum: 167}, |
120 | {.Names: {"r19d", "r19w", "r19b"}, .RegNum: 168}, |
121 | {.Names: {"r20d", "r20w", "r20b"}, .RegNum: 169}, |
122 | {.Names: {"r21d", "r21w", "r21b"}, .RegNum: 170}, |
123 | {.Names: {"r22d", "r22w", "r22b"}, .RegNum: 171}, |
124 | {.Names: {"r23d", "r23w", "r23b"}, .RegNum: 172}, |
125 | {.Names: {"r24d", "r24w", "r24b"}, .RegNum: 173}, |
126 | {.Names: {"r25d", "r25w", "r25b"}, .RegNum: 174}, |
127 | {.Names: {"r26d", "r26w", "r26b"}, .RegNum: 175}, |
128 | {.Names: {"r27d", "r27w", "r27b"}, .RegNum: 176}, |
129 | {.Names: {"r28d", "r28w", "r28b"}, .RegNum: 177}, |
130 | {.Names: {"r29d", "r29w", "r29b"}, .RegNum: 178}, |
131 | {.Names: {"r30d", "r30w", "r30b"}, .RegNum: 179}, |
132 | {.Names: {"r31d", "r31w", "r31b"}, .RegNum: 180}, |
133 | }; |
134 | } // namespace targets |
135 | } // namespace clang |
136 | |
137 | using namespace clang; |
138 | using namespace clang::targets; |
139 | |
140 | bool X86TargetInfo::setFPMath(StringRef Name) { |
141 | if (Name == "387") { |
142 | FPMath = FP_387; |
143 | return true; |
144 | } |
145 | if (Name == "sse") { |
146 | FPMath = FP_SSE; |
147 | return true; |
148 | } |
149 | return false; |
150 | } |
151 | |
152 | bool X86TargetInfo::initFeatureMap( |
153 | llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, |
154 | const std::vector<std::string> &FeaturesVec) const { |
155 | // FIXME: This *really* should not be here. |
156 | // X86_64 always has SSE2. |
157 | if (getTriple().getArch() == llvm::Triple::x86_64) |
158 | setFeatureEnabled(Features, Name: "sse2", Enabled: true); |
159 | |
160 | using namespace llvm::X86; |
161 | |
162 | SmallVector<StringRef, 16> CPUFeatures; |
163 | getFeaturesForCPU(CPU, Features&: CPUFeatures); |
164 | for (auto &F : CPUFeatures) |
165 | setFeatureEnabled(Features, Name: F, Enabled: true); |
166 | |
167 | std::vector<std::string> UpdatedFeaturesVec; |
168 | std::vector<std::string> UpdatedAVX10FeaturesVec; |
169 | enum { FE_NOSET = -1, FE_FALSE, FE_TRUE }; |
170 | int HasEVEX512 = FE_NOSET; |
171 | bool HasAVX512F = Features.lookup(Key: "avx512f"); |
172 | bool HasAVX10 = Features.lookup(Key: "avx10.1-256"); |
173 | bool HasAVX10_512 = Features.lookup(Key: "avx10.1-512"); |
174 | std::string LastAVX10; |
175 | std::string LastAVX512; |
176 | for (const auto &Feature : FeaturesVec) { |
177 | // Expand general-regs-only to -x86, -mmx and -sse |
178 | if (Feature == "+general-regs-only") { |
179 | UpdatedFeaturesVec.push_back(x: "-x87"); |
180 | UpdatedFeaturesVec.push_back(x: "-mmx"); |
181 | UpdatedFeaturesVec.push_back(x: "-sse"); |
182 | continue; |
183 | } |
184 | |
185 | if (Feature.substr(pos: 1, n: 6) == "avx10.") { |
186 | if (Feature[0] == '+') { |
187 | HasAVX10 = true; |
188 | if (StringRef(Feature).ends_with(Suffix: "512")) |
189 | HasAVX10_512 = true; |
190 | LastAVX10 = Feature; |
191 | } else if (HasAVX10 && Feature == "-avx10.1-256") { |
192 | HasAVX10 = false; |
193 | HasAVX10_512 = false; |
194 | } else if (HasAVX10_512 && Feature == "-avx10.1-512") { |
195 | HasAVX10_512 = false; |
196 | } |
197 | // Postpone AVX10 features handling after AVX512 settled. |
198 | UpdatedAVX10FeaturesVec.push_back(x: Feature); |
199 | continue; |
200 | } else if (!HasAVX512F && StringRef(Feature).starts_with(Prefix: "+avx512")) { |
201 | HasAVX512F = true; |
202 | LastAVX512 = Feature; |
203 | } else if (HasAVX512F && Feature == "-avx512f") { |
204 | HasAVX512F = false; |
205 | } else if (HasEVEX512 != FE_TRUE && Feature == "+evex512") { |
206 | HasEVEX512 = FE_TRUE; |
207 | continue; |
208 | } else if (HasEVEX512 != FE_FALSE && Feature == "-evex512") { |
209 | HasEVEX512 = FE_FALSE; |
210 | continue; |
211 | } |
212 | |
213 | UpdatedFeaturesVec.push_back(x: Feature); |
214 | } |
215 | llvm::append_range(C&: UpdatedFeaturesVec, R&: UpdatedAVX10FeaturesVec); |
216 | // HasEVEX512 is a three-states flag. We need to turn it into [+-]evex512 |
217 | // according to other features. |
218 | if (!HasAVX10_512 && HasAVX512F) { |
219 | UpdatedFeaturesVec.push_back(x: HasEVEX512 == FE_FALSE ? "-evex512" |
220 | : "+evex512"); |
221 | if (HasAVX10 && HasEVEX512 != FE_FALSE) |
222 | Diags.Report(diag::warn_invalid_feature_combination) |
223 | << LastAVX512 + " "+ LastAVX10 + "; will be promoted to avx10.1-512"; |
224 | } else if (HasAVX10) { |
225 | if (!HasAVX512F && HasEVEX512 != FE_NOSET) |
226 | Diags.Report(diag::warn_invalid_feature_combination) |
227 | << LastAVX10 + (HasEVEX512 == FE_TRUE ? " +evex512": " -evex512"); |
228 | UpdatedFeaturesVec.push_back(x: HasAVX10_512 ? "+evex512": "-evex512"); |
229 | } |
230 | |
231 | if (!TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec: UpdatedFeaturesVec)) |
232 | return false; |
233 | |
234 | // Can't do this earlier because we need to be able to explicitly enable |
235 | // or disable these features and the things that they depend upon. |
236 | |
237 | // Enable popcnt if sse4.2 is enabled and popcnt is not explicitly disabled. |
238 | auto I = Features.find(Key: "sse4.2"); |
239 | if (I != Features.end() && I->getValue() && |
240 | !llvm::is_contained(Range&: UpdatedFeaturesVec, Element: "-popcnt")) |
241 | Features["popcnt"] = true; |
242 | |
243 | // Additionally, if SSE is enabled and mmx is not explicitly disabled, |
244 | // then enable MMX. |
245 | I = Features.find(Key: "sse"); |
246 | if (I != Features.end() && I->getValue() && |
247 | !llvm::is_contained(Range&: UpdatedFeaturesVec, Element: "-mmx")) |
248 | Features["mmx"] = true; |
249 | |
250 | // Enable xsave if avx is enabled and xsave is not explicitly disabled. |
251 | I = Features.find(Key: "avx"); |
252 | if (I != Features.end() && I->getValue() && |
253 | !llvm::is_contained(Range&: UpdatedFeaturesVec, Element: "-xsave")) |
254 | Features["xsave"] = true; |
255 | |
256 | // Enable CRC32 if SSE4.2 is enabled and CRC32 is not explicitly disabled. |
257 | I = Features.find(Key: "sse4.2"); |
258 | if (I != Features.end() && I->getValue() && |
259 | !llvm::is_contained(Range&: UpdatedFeaturesVec, Element: "-crc32")) |
260 | Features["crc32"] = true; |
261 | |
262 | return true; |
263 | } |
264 | |
265 | void X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, |
266 | StringRef Name, bool Enabled) const { |
267 | if (Name == "sse4") { |
268 | // We can get here via the __target__ attribute since that's not controlled |
269 | // via the -msse4/-mno-sse4 command line alias. Handle this the same way |
270 | // here - turn on the sse4.2 if enabled, turn off the sse4.1 level if |
271 | // disabled. |
272 | if (Enabled) |
273 | Name = "sse4.2"; |
274 | else |
275 | Name = "sse4.1"; |
276 | } |
277 | |
278 | Features[Name] = Enabled; |
279 | llvm::X86::updateImpliedFeatures(Feature: Name, Enabled, Features); |
280 | } |
281 | |
282 | /// handleTargetFeatures - Perform initialization based on the user |
283 | /// configured set of features. |
284 | bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, |
285 | DiagnosticsEngine &Diags) { |
286 | for (const auto &Feature : Features) { |
287 | if (Feature[0] != '+') |
288 | continue; |
289 | |
290 | if (Feature == "+mmx") { |
291 | HasMMX = true; |
292 | } else if (Feature == "+aes") { |
293 | HasAES = true; |
294 | } else if (Feature == "+vaes") { |
295 | HasVAES = true; |
296 | } else if (Feature == "+pclmul") { |
297 | HasPCLMUL = true; |
298 | } else if (Feature == "+vpclmulqdq") { |
299 | HasVPCLMULQDQ = true; |
300 | } else if (Feature == "+lzcnt") { |
301 | HasLZCNT = true; |
302 | } else if (Feature == "+rdrnd") { |
303 | HasRDRND = true; |
304 | } else if (Feature == "+fsgsbase") { |
305 | HasFSGSBASE = true; |
306 | } else if (Feature == "+bmi") { |
307 | HasBMI = true; |
308 | } else if (Feature == "+bmi2") { |
309 | HasBMI2 = true; |
310 | } else if (Feature == "+popcnt") { |
311 | HasPOPCNT = true; |
312 | } else if (Feature == "+rtm") { |
313 | HasRTM = true; |
314 | } else if (Feature == "+prfchw") { |
315 | HasPRFCHW = true; |
316 | } else if (Feature == "+rdseed") { |
317 | HasRDSEED = true; |
318 | } else if (Feature == "+adx") { |
319 | HasADX = true; |
320 | } else if (Feature == "+tbm") { |
321 | HasTBM = true; |
322 | } else if (Feature == "+lwp") { |
323 | HasLWP = true; |
324 | } else if (Feature == "+fma") { |
325 | HasFMA = true; |
326 | } else if (Feature == "+f16c") { |
327 | HasF16C = true; |
328 | } else if (Feature == "+gfni") { |
329 | HasGFNI = true; |
330 | } else if (Feature == "+evex512") { |
331 | HasEVEX512 = true; |
332 | } else if (Feature == "+avx10.1-256") { |
333 | HasAVX10_1 = true; |
334 | } else if (Feature == "+avx10.1-512") { |
335 | HasAVX10_1_512 = true; |
336 | } else if (Feature == "+avx10.2-256") { |
337 | HasAVX10_2 = true; |
338 | HasFullBFloat16 = true; |
339 | } else if (Feature == "+avx10.2-512") { |
340 | HasAVX10_2_512 = true; |
341 | } else if (Feature == "+avx512cd") { |
342 | HasAVX512CD = true; |
343 | } else if (Feature == "+avx512vpopcntdq") { |
344 | HasAVX512VPOPCNTDQ = true; |
345 | } else if (Feature == "+avx512vnni") { |
346 | HasAVX512VNNI = true; |
347 | } else if (Feature == "+avx512bf16") { |
348 | HasAVX512BF16 = true; |
349 | } else if (Feature == "+avx512fp16") { |
350 | HasAVX512FP16 = true; |
351 | HasLegalHalfType = true; |
352 | } else if (Feature == "+avx512dq") { |
353 | HasAVX512DQ = true; |
354 | } else if (Feature == "+avx512bitalg") { |
355 | HasAVX512BITALG = true; |
356 | } else if (Feature == "+avx512bw") { |
357 | HasAVX512BW = true; |
358 | } else if (Feature == "+avx512vl") { |
359 | HasAVX512VL = true; |
360 | } else if (Feature == "+avx512vbmi") { |
361 | HasAVX512VBMI = true; |
362 | } else if (Feature == "+avx512vbmi2") { |
363 | HasAVX512VBMI2 = true; |
364 | } else if (Feature == "+avx512ifma") { |
365 | HasAVX512IFMA = true; |
366 | } else if (Feature == "+avx512vp2intersect") { |
367 | HasAVX512VP2INTERSECT = true; |
368 | } else if (Feature == "+sha") { |
369 | HasSHA = true; |
370 | } else if (Feature == "+sha512") { |
371 | HasSHA512 = true; |
372 | } else if (Feature == "+shstk") { |
373 | HasSHSTK = true; |
374 | } else if (Feature == "+sm3") { |
375 | HasSM3 = true; |
376 | } else if (Feature == "+sm4") { |
377 | HasSM4 = true; |
378 | } else if (Feature == "+movbe") { |
379 | HasMOVBE = true; |
380 | } else if (Feature == "+movrs") { |
381 | HasMOVRS = true; |
382 | } else if (Feature == "+sgx") { |
383 | HasSGX = true; |
384 | } else if (Feature == "+cx8") { |
385 | HasCX8 = true; |
386 | } else if (Feature == "+cx16") { |
387 | HasCX16 = true; |
388 | } else if (Feature == "+fxsr") { |
389 | HasFXSR = true; |
390 | } else if (Feature == "+xsave") { |
391 | HasXSAVE = true; |
392 | } else if (Feature == "+xsaveopt") { |
393 | HasXSAVEOPT = true; |
394 | } else if (Feature == "+xsavec") { |
395 | HasXSAVEC = true; |
396 | } else if (Feature == "+xsaves") { |
397 | HasXSAVES = true; |
398 | } else if (Feature == "+mwaitx") { |
399 | HasMWAITX = true; |
400 | } else if (Feature == "+pku") { |
401 | HasPKU = true; |
402 | } else if (Feature == "+clflushopt") { |
403 | HasCLFLUSHOPT = true; |
404 | } else if (Feature == "+clwb") { |
405 | HasCLWB = true; |
406 | } else if (Feature == "+wbnoinvd") { |
407 | HasWBNOINVD = true; |
408 | } else if (Feature == "+prefetchi") { |
409 | HasPREFETCHI = true; |
410 | } else if (Feature == "+clzero") { |
411 | HasCLZERO = true; |
412 | } else if (Feature == "+cldemote") { |
413 | HasCLDEMOTE = true; |
414 | } else if (Feature == "+rdpid") { |
415 | HasRDPID = true; |
416 | } else if (Feature == "+rdpru") { |
417 | HasRDPRU = true; |
418 | } else if (Feature == "+kl") { |
419 | HasKL = true; |
420 | } else if (Feature == "+widekl") { |
421 | HasWIDEKL = true; |
422 | } else if (Feature == "+retpoline-external-thunk") { |
423 | HasRetpolineExternalThunk = true; |
424 | } else if (Feature == "+sahf") { |
425 | HasLAHFSAHF = true; |
426 | } else if (Feature == "+waitpkg") { |
427 | HasWAITPKG = true; |
428 | } else if (Feature == "+movdiri") { |
429 | HasMOVDIRI = true; |
430 | } else if (Feature == "+movdir64b") { |
431 | HasMOVDIR64B = true; |
432 | } else if (Feature == "+pconfig") { |
433 | HasPCONFIG = true; |
434 | } else if (Feature == "+ptwrite") { |
435 | HasPTWRITE = true; |
436 | } else if (Feature == "+invpcid") { |
437 | HasINVPCID = true; |
438 | } else if (Feature == "+enqcmd") { |
439 | HasENQCMD = true; |
440 | } else if (Feature == "+hreset") { |
441 | HasHRESET = true; |
442 | } else if (Feature == "+amx-bf16") { |
443 | HasAMXBF16 = true; |
444 | } else if (Feature == "+amx-fp16") { |
445 | HasAMXFP16 = true; |
446 | } else if (Feature == "+amx-int8") { |
447 | HasAMXINT8 = true; |
448 | } else if (Feature == "+amx-tile") { |
449 | HasAMXTILE = true; |
450 | } else if (Feature == "+amx-complex") { |
451 | HasAMXCOMPLEX = true; |
452 | } else if (Feature == "+amx-fp8") { |
453 | HasAMXFP8 = true; |
454 | } else if (Feature == "+amx-movrs") { |
455 | HasAMXMOVRS = true; |
456 | } else if (Feature == "+amx-transpose") { |
457 | HasAMXTRANSPOSE = true; |
458 | } else if (Feature == "+amx-avx512") { |
459 | HasAMXAVX512 = true; |
460 | } else if (Feature == "+amx-tf32") { |
461 | HasAMXTF32 = true; |
462 | } else if (Feature == "+cmpccxadd") { |
463 | HasCMPCCXADD = true; |
464 | } else if (Feature == "+raoint") { |
465 | HasRAOINT = true; |
466 | } else if (Feature == "+avxifma") { |
467 | HasAVXIFMA = true; |
468 | } else if (Feature == "+avxneconvert") { |
469 | HasAVXNECONVERT= true; |
470 | } else if (Feature == "+avxvnni") { |
471 | HasAVXVNNI = true; |
472 | } else if (Feature == "+avxvnniint16") { |
473 | HasAVXVNNIINT16 = true; |
474 | } else if (Feature == "+avxvnniint8") { |
475 | HasAVXVNNIINT8 = true; |
476 | } else if (Feature == "+serialize") { |
477 | HasSERIALIZE = true; |
478 | } else if (Feature == "+tsxldtrk") { |
479 | HasTSXLDTRK = true; |
480 | } else if (Feature == "+uintr") { |
481 | HasUINTR = true; |
482 | } else if (Feature == "+usermsr") { |
483 | HasUSERMSR = true; |
484 | } else if (Feature == "+crc32") { |
485 | HasCRC32 = true; |
486 | } else if (Feature == "+x87") { |
487 | HasX87 = true; |
488 | } else if (Feature == "+fullbf16") { |
489 | HasFullBFloat16 = true; |
490 | } else if (Feature == "+egpr") { |
491 | HasEGPR = true; |
492 | } else if (Feature == "+inline-asm-use-gpr32") { |
493 | HasInlineAsmUseGPR32 = true; |
494 | } else if (Feature == "+push2pop2") { |
495 | HasPush2Pop2 = true; |
496 | } else if (Feature == "+ppx") { |
497 | HasPPX = true; |
498 | } else if (Feature == "+ndd") { |
499 | HasNDD = true; |
500 | } else if (Feature == "+ccmp") { |
501 | HasCCMP = true; |
502 | } else if (Feature == "+nf") { |
503 | HasNF = true; |
504 | } else if (Feature == "+cf") { |
505 | HasCF = true; |
506 | } else if (Feature == "+zu") { |
507 | HasZU = true; |
508 | } else if (Feature == "+branch-hint") { |
509 | HasBranchHint = true; |
510 | } |
511 | |
512 | X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Feature) |
513 | .Case(S: "+avx512f", Value: AVX512F) |
514 | .Case(S: "+avx2", Value: AVX2) |
515 | .Case(S: "+avx", Value: AVX) |
516 | .Case(S: "+sse4.2", Value: SSE42) |
517 | .Case(S: "+sse4.1", Value: SSE41) |
518 | .Case(S: "+ssse3", Value: SSSE3) |
519 | .Case(S: "+sse3", Value: SSE3) |
520 | .Case(S: "+sse2", Value: SSE2) |
521 | .Case(S: "+sse", Value: SSE1) |
522 | .Default(Value: NoSSE); |
523 | SSELevel = std::max(a: SSELevel, b: Level); |
524 | |
525 | HasFloat16 = SSELevel >= SSE2; |
526 | |
527 | // X86 target has bfloat16 emulation support in the backend, where |
528 | // bfloat16 is treated as a 32-bit float, arithmetic operations are |
529 | // performed in 32-bit, and the result is converted back to bfloat16. |
530 | // Truncation and extension between bfloat16 and 32-bit float are supported |
531 | // by the compiler-rt library. However, native bfloat16 support is currently |
532 | // not available in the X86 target. Hence, HasFullBFloat16 will be false |
533 | // until native bfloat16 support is available. HasFullBFloat16 is used to |
534 | // determine whether to automatically use excess floating point precision |
535 | // for bfloat16 arithmetic operations in the front-end. |
536 | HasBFloat16 = SSELevel >= SSE2; |
537 | |
538 | XOPEnum XLevel = llvm::StringSwitch<XOPEnum>(Feature) |
539 | .Case(S: "+xop", Value: XOP) |
540 | .Case(S: "+fma4", Value: FMA4) |
541 | .Case(S: "+sse4a", Value: SSE4A) |
542 | .Default(Value: NoXOP); |
543 | XOPLevel = std::max(a: XOPLevel, b: XLevel); |
544 | } |
545 | |
546 | // LLVM doesn't have a separate switch for fpmath, so only accept it if it |
547 | // matches the selected sse level. |
548 | if ((FPMath == FP_SSE && SSELevel < SSE1) || |
549 | (FPMath == FP_387 && SSELevel >= SSE1)) { |
550 | Diags.Report(diag::err_target_unsupported_fpmath) |
551 | << (FPMath == FP_SSE ? "sse": "387"); |
552 | return false; |
553 | } |
554 | |
555 | // FIXME: We should allow long double type on 32-bits to match with GCC. |
556 | // This requires backend to be able to lower f80 without x87 first. |
557 | if (!HasX87 && LongDoubleFormat == &llvm::APFloat::x87DoubleExtended()) |
558 | HasLongDouble = false; |
559 | |
560 | return true; |
561 | } |
562 | |
563 | /// X86TargetInfo::getTargetDefines - Return the set of the X86-specific macro |
564 | /// definitions for this particular subtarget. |
565 | void X86TargetInfo::getTargetDefines(const LangOptions &Opts, |
566 | MacroBuilder &Builder) const { |
567 | // Inline assembly supports X86 flag outputs. |
568 | Builder.defineMacro(Name: "__GCC_ASM_FLAG_OUTPUTS__"); |
569 | |
570 | std::string CodeModel = getTargetOpts().CodeModel; |
571 | if (CodeModel == "default") |
572 | CodeModel = "small"; |
573 | Builder.defineMacro(Name: "__code_model_"+ CodeModel + "__"); |
574 | |
575 | // Target identification. |
576 | if (getTriple().getArch() == llvm::Triple::x86_64) { |
577 | Builder.defineMacro(Name: "__amd64__"); |
578 | Builder.defineMacro(Name: "__amd64"); |
579 | Builder.defineMacro(Name: "__x86_64"); |
580 | Builder.defineMacro(Name: "__x86_64__"); |
581 | if (getTriple().getArchName() == "x86_64h") { |
582 | Builder.defineMacro(Name: "__x86_64h"); |
583 | Builder.defineMacro(Name: "__x86_64h__"); |
584 | } |
585 | } else { |
586 | DefineStd(Builder, MacroName: "i386", Opts); |
587 | } |
588 | |
589 | Builder.defineMacro(Name: "__SEG_GS"); |
590 | Builder.defineMacro(Name: "__SEG_FS"); |
591 | Builder.defineMacro(Name: "__seg_gs", Value: "__attribute__((address_space(256)))"); |
592 | Builder.defineMacro(Name: "__seg_fs", Value: "__attribute__((address_space(257)))"); |
593 | |
594 | // Subtarget options. |
595 | // FIXME: We are hard-coding the tune parameters based on the CPU, but they |
596 | // truly should be based on -mtune options. |
597 | using namespace llvm::X86; |
598 | switch (CPU) { |
599 | case CK_None: |
600 | break; |
601 | case CK_i386: |
602 | // The rest are coming from the i386 define above. |
603 | Builder.defineMacro(Name: "__tune_i386__"); |
604 | break; |
605 | case CK_i486: |
606 | case CK_WinChipC6: |
607 | case CK_WinChip2: |
608 | case CK_C3: |
609 | defineCPUMacros(Builder, CPUName: "i486"); |
610 | break; |
611 | case CK_PentiumMMX: |
612 | Builder.defineMacro(Name: "__pentium_mmx__"); |
613 | Builder.defineMacro(Name: "__tune_pentium_mmx__"); |
614 | [[fallthrough]]; |
615 | case CK_i586: |
616 | case CK_Pentium: |
617 | defineCPUMacros(Builder, CPUName: "i586"); |
618 | defineCPUMacros(Builder, CPUName: "pentium"); |
619 | break; |
620 | case CK_Pentium3: |
621 | case CK_PentiumM: |
622 | Builder.defineMacro(Name: "__tune_pentium3__"); |
623 | [[fallthrough]]; |
624 | case CK_Pentium2: |
625 | case CK_C3_2: |
626 | Builder.defineMacro(Name: "__tune_pentium2__"); |
627 | [[fallthrough]]; |
628 | case CK_PentiumPro: |
629 | case CK_i686: |
630 | defineCPUMacros(Builder, CPUName: "i686"); |
631 | defineCPUMacros(Builder, CPUName: "pentiumpro"); |
632 | break; |
633 | case CK_Pentium4: |
634 | defineCPUMacros(Builder, CPUName: "pentium4"); |
635 | break; |
636 | case CK_Yonah: |
637 | case CK_Prescott: |
638 | case CK_Nocona: |
639 | defineCPUMacros(Builder, CPUName: "nocona"); |
640 | break; |
641 | case CK_Core2: |
642 | case CK_Penryn: |
643 | defineCPUMacros(Builder, CPUName: "core2"); |
644 | break; |
645 | case CK_Bonnell: |
646 | defineCPUMacros(Builder, CPUName: "atom"); |
647 | break; |
648 | case CK_Silvermont: |
649 | defineCPUMacros(Builder, CPUName: "slm"); |
650 | break; |
651 | case CK_Goldmont: |
652 | defineCPUMacros(Builder, CPUName: "goldmont"); |
653 | break; |
654 | case CK_GoldmontPlus: |
655 | defineCPUMacros(Builder, CPUName: "goldmont_plus"); |
656 | break; |
657 | case CK_Tremont: |
658 | defineCPUMacros(Builder, CPUName: "tremont"); |
659 | break; |
660 | // Gracemont and later atom-cores use P-core cpu macros. |
661 | case CK_Gracemont: |
662 | case CK_Nehalem: |
663 | case CK_Westmere: |
664 | case CK_SandyBridge: |
665 | case CK_IvyBridge: |
666 | case CK_Haswell: |
667 | case CK_Broadwell: |
668 | case CK_SkylakeClient: |
669 | case CK_SkylakeServer: |
670 | case CK_Cascadelake: |
671 | case CK_Cooperlake: |
672 | case CK_Cannonlake: |
673 | case CK_IcelakeClient: |
674 | case CK_Rocketlake: |
675 | case CK_IcelakeServer: |
676 | case CK_Tigerlake: |
677 | case CK_SapphireRapids: |
678 | case CK_Alderlake: |
679 | case CK_Raptorlake: |
680 | case CK_Meteorlake: |
681 | case CK_Arrowlake: |
682 | case CK_ArrowlakeS: |
683 | case CK_Lunarlake: |
684 | case CK_Pantherlake: |
685 | case CK_Sierraforest: |
686 | case CK_Grandridge: |
687 | case CK_Graniterapids: |
688 | case CK_GraniterapidsD: |
689 | case CK_Emeraldrapids: |
690 | case CK_Clearwaterforest: |
691 | case CK_Diamondrapids: |
692 | // FIXME: Historically, we defined this legacy name, it would be nice to |
693 | // remove it at some point. We've never exposed fine-grained names for |
694 | // recent primary x86 CPUs, and we should keep it that way. |
695 | defineCPUMacros(Builder, CPUName: "corei7"); |
696 | break; |
697 | case CK_KNL: |
698 | defineCPUMacros(Builder, CPUName: "knl"); |
699 | break; |
700 | case CK_KNM: |
701 | break; |
702 | case CK_Lakemont: |
703 | defineCPUMacros(Builder, CPUName: "i586", /*Tuning*/false); |
704 | defineCPUMacros(Builder, CPUName: "pentium", /*Tuning*/false); |
705 | Builder.defineMacro(Name: "__tune_lakemont__"); |
706 | break; |
707 | case CK_K6_2: |
708 | Builder.defineMacro(Name: "__k6_2__"); |
709 | Builder.defineMacro(Name: "__tune_k6_2__"); |
710 | [[fallthrough]]; |
711 | case CK_K6_3: |
712 | if (CPU != CK_K6_2) { // In case of fallthrough |
713 | // FIXME: GCC may be enabling these in cases where some other k6 |
714 | // architecture is specified but -m3dnow is explicitly provided. The |
715 | // exact semantics need to be determined and emulated here. |
716 | Builder.defineMacro(Name: "__k6_3__"); |
717 | Builder.defineMacro(Name: "__tune_k6_3__"); |
718 | } |
719 | [[fallthrough]]; |
720 | case CK_K6: |
721 | defineCPUMacros(Builder, CPUName: "k6"); |
722 | break; |
723 | case CK_Athlon: |
724 | case CK_AthlonXP: |
725 | defineCPUMacros(Builder, CPUName: "athlon"); |
726 | if (SSELevel != NoSSE) { |
727 | Builder.defineMacro(Name: "__athlon_sse__"); |
728 | Builder.defineMacro(Name: "__tune_athlon_sse__"); |
729 | } |
730 | break; |
731 | case CK_K8: |
732 | case CK_K8SSE3: |
733 | case CK_x86_64: |
734 | defineCPUMacros(Builder, CPUName: "k8"); |
735 | break; |
736 | case CK_x86_64_v2: |
737 | case CK_x86_64_v3: |
738 | case CK_x86_64_v4: |
739 | break; |
740 | case CK_AMDFAM10: |
741 | defineCPUMacros(Builder, CPUName: "amdfam10"); |
742 | break; |
743 | case CK_BTVER1: |
744 | defineCPUMacros(Builder, CPUName: "btver1"); |
745 | break; |
746 | case CK_BTVER2: |
747 | defineCPUMacros(Builder, CPUName: "btver2"); |
748 | break; |
749 | case CK_BDVER1: |
750 | defineCPUMacros(Builder, CPUName: "bdver1"); |
751 | break; |
752 | case CK_BDVER2: |
753 | defineCPUMacros(Builder, CPUName: "bdver2"); |
754 | break; |
755 | case CK_BDVER3: |
756 | defineCPUMacros(Builder, CPUName: "bdver3"); |
757 | break; |
758 | case CK_BDVER4: |
759 | defineCPUMacros(Builder, CPUName: "bdver4"); |
760 | break; |
761 | case CK_ZNVER1: |
762 | defineCPUMacros(Builder, CPUName: "znver1"); |
763 | break; |
764 | case CK_ZNVER2: |
765 | defineCPUMacros(Builder, CPUName: "znver2"); |
766 | break; |
767 | case CK_ZNVER3: |
768 | defineCPUMacros(Builder, CPUName: "znver3"); |
769 | break; |
770 | case CK_ZNVER4: |
771 | defineCPUMacros(Builder, CPUName: "znver4"); |
772 | break; |
773 | case CK_ZNVER5: |
774 | defineCPUMacros(Builder, CPUName: "znver5"); |
775 | break; |
776 | case CK_Geode: |
777 | defineCPUMacros(Builder, CPUName: "geode"); |
778 | break; |
779 | } |
780 | |
781 | // Target properties. |
782 | Builder.defineMacro(Name: "__REGISTER_PREFIX__", Value: ""); |
783 | |
784 | // Define __NO_MATH_INLINES on linux/x86 so that we don't get inline |
785 | // functions in glibc header files that use FP Stack inline asm which the |
786 | // backend can't deal with (PR879). |
787 | Builder.defineMacro(Name: "__NO_MATH_INLINES"); |
788 | |
789 | if (HasAES) |
790 | Builder.defineMacro(Name: "__AES__"); |
791 | |
792 | if (HasVAES) |
793 | Builder.defineMacro(Name: "__VAES__"); |
794 | |
795 | if (HasPCLMUL) |
796 | Builder.defineMacro(Name: "__PCLMUL__"); |
797 | |
798 | if (HasVPCLMULQDQ) |
799 | Builder.defineMacro(Name: "__VPCLMULQDQ__"); |
800 | |
801 | // Note, in 32-bit mode, GCC does not define the macro if -mno-sahf. In LLVM, |
802 | // the feature flag only applies to 64-bit mode. |
803 | if (HasLAHFSAHF || getTriple().getArch() == llvm::Triple::x86) |
804 | Builder.defineMacro(Name: "__LAHF_SAHF__"); |
805 | |
806 | if (HasLZCNT) |
807 | Builder.defineMacro(Name: "__LZCNT__"); |
808 | |
809 | if (HasRDRND) |
810 | Builder.defineMacro(Name: "__RDRND__"); |
811 | |
812 | if (HasFSGSBASE) |
813 | Builder.defineMacro(Name: "__FSGSBASE__"); |
814 | |
815 | if (HasBMI) |
816 | Builder.defineMacro(Name: "__BMI__"); |
817 | |
818 | if (HasBMI2) |
819 | Builder.defineMacro(Name: "__BMI2__"); |
820 | |
821 | if (HasPOPCNT) |
822 | Builder.defineMacro(Name: "__POPCNT__"); |
823 | |
824 | if (HasRTM) |
825 | Builder.defineMacro(Name: "__RTM__"); |
826 | |
827 | if (HasPRFCHW) |
828 | Builder.defineMacro(Name: "__PRFCHW__"); |
829 | |
830 | if (HasRDSEED) |
831 | Builder.defineMacro(Name: "__RDSEED__"); |
832 | |
833 | if (HasADX) |
834 | Builder.defineMacro(Name: "__ADX__"); |
835 | |
836 | if (HasTBM) |
837 | Builder.defineMacro(Name: "__TBM__"); |
838 | |
839 | if (HasLWP) |
840 | Builder.defineMacro(Name: "__LWP__"); |
841 | |
842 | if (HasMWAITX) |
843 | Builder.defineMacro(Name: "__MWAITX__"); |
844 | |
845 | if (HasMOVBE) |
846 | Builder.defineMacro(Name: "__MOVBE__"); |
847 | |
848 | switch (XOPLevel) { |
849 | case XOP: |
850 | Builder.defineMacro(Name: "__XOP__"); |
851 | [[fallthrough]]; |
852 | case FMA4: |
853 | Builder.defineMacro(Name: "__FMA4__"); |
854 | [[fallthrough]]; |
855 | case SSE4A: |
856 | Builder.defineMacro(Name: "__SSE4A__"); |
857 | [[fallthrough]]; |
858 | case NoXOP: |
859 | break; |
860 | } |
861 | |
862 | if (HasFMA) |
863 | Builder.defineMacro(Name: "__FMA__"); |
864 | |
865 | if (HasF16C) |
866 | Builder.defineMacro(Name: "__F16C__"); |
867 | |
868 | if (HasGFNI) |
869 | Builder.defineMacro(Name: "__GFNI__"); |
870 | |
871 | if (HasEVEX512) |
872 | Builder.defineMacro(Name: "__EVEX512__"); |
873 | if (HasAVX10_1) |
874 | Builder.defineMacro(Name: "__AVX10_1__"); |
875 | if (HasAVX10_1_512) |
876 | Builder.defineMacro(Name: "__AVX10_1_512__"); |
877 | if (HasAVX10_2) |
878 | Builder.defineMacro(Name: "__AVX10_2__"); |
879 | if (HasAVX10_2_512) |
880 | Builder.defineMacro(Name: "__AVX10_2_512__"); |
881 | if (HasAVX512CD) |
882 | Builder.defineMacro(Name: "__AVX512CD__"); |
883 | if (HasAVX512VPOPCNTDQ) |
884 | Builder.defineMacro(Name: "__AVX512VPOPCNTDQ__"); |
885 | if (HasAVX512VNNI) |
886 | Builder.defineMacro(Name: "__AVX512VNNI__"); |
887 | if (HasAVX512BF16) |
888 | Builder.defineMacro(Name: "__AVX512BF16__"); |
889 | if (HasAVX512FP16) |
890 | Builder.defineMacro(Name: "__AVX512FP16__"); |
891 | if (HasAVX512DQ) |
892 | Builder.defineMacro(Name: "__AVX512DQ__"); |
893 | if (HasAVX512BITALG) |
894 | Builder.defineMacro(Name: "__AVX512BITALG__"); |
895 | if (HasAVX512BW) |
896 | Builder.defineMacro(Name: "__AVX512BW__"); |
897 | if (HasAVX512VL) { |
898 | Builder.defineMacro(Name: "__AVX512VL__"); |
899 | Builder.defineMacro(Name: "__EVEX256__"); |
900 | } |
901 | if (HasAVX512VBMI) |
902 | Builder.defineMacro(Name: "__AVX512VBMI__"); |
903 | if (HasAVX512VBMI2) |
904 | Builder.defineMacro(Name: "__AVX512VBMI2__"); |
905 | if (HasAVX512IFMA) |
906 | Builder.defineMacro(Name: "__AVX512IFMA__"); |
907 | if (HasAVX512VP2INTERSECT) |
908 | Builder.defineMacro(Name: "__AVX512VP2INTERSECT__"); |
909 | if (HasSHA) |
910 | Builder.defineMacro(Name: "__SHA__"); |
911 | if (HasSHA512) |
912 | Builder.defineMacro(Name: "__SHA512__"); |
913 | |
914 | if (HasFXSR) |
915 | Builder.defineMacro(Name: "__FXSR__"); |
916 | if (HasXSAVE) |
917 | Builder.defineMacro(Name: "__XSAVE__"); |
918 | if (HasXSAVEOPT) |
919 | Builder.defineMacro(Name: "__XSAVEOPT__"); |
920 | if (HasXSAVEC) |
921 | Builder.defineMacro(Name: "__XSAVEC__"); |
922 | if (HasXSAVES) |
923 | Builder.defineMacro(Name: "__XSAVES__"); |
924 | if (HasPKU) |
925 | Builder.defineMacro(Name: "__PKU__"); |
926 | if (HasCLFLUSHOPT) |
927 | Builder.defineMacro(Name: "__CLFLUSHOPT__"); |
928 | if (HasCLWB) |
929 | Builder.defineMacro(Name: "__CLWB__"); |
930 | if (HasWBNOINVD) |
931 | Builder.defineMacro(Name: "__WBNOINVD__"); |
932 | if (HasSHSTK) |
933 | Builder.defineMacro(Name: "__SHSTK__"); |
934 | if (HasSGX) |
935 | Builder.defineMacro(Name: "__SGX__"); |
936 | if (HasSM3) |
937 | Builder.defineMacro(Name: "__SM3__"); |
938 | if (HasSM4) |
939 | Builder.defineMacro(Name: "__SM4__"); |
940 | if (HasPREFETCHI) |
941 | Builder.defineMacro(Name: "__PREFETCHI__"); |
942 | if (HasCLZERO) |
943 | Builder.defineMacro(Name: "__CLZERO__"); |
944 | if (HasKL) |
945 | Builder.defineMacro(Name: "__KL__"); |
946 | if (HasWIDEKL) |
947 | Builder.defineMacro(Name: "__WIDEKL__"); |
948 | if (HasRDPID) |
949 | Builder.defineMacro(Name: "__RDPID__"); |
950 | if (HasRDPRU) |
951 | Builder.defineMacro(Name: "__RDPRU__"); |
952 | if (HasCLDEMOTE) |
953 | Builder.defineMacro(Name: "__CLDEMOTE__"); |
954 | if (HasWAITPKG) |
955 | Builder.defineMacro(Name: "__WAITPKG__"); |
956 | if (HasMOVDIRI) |
957 | Builder.defineMacro(Name: "__MOVDIRI__"); |
958 | if (HasMOVDIR64B) |
959 | Builder.defineMacro(Name: "__MOVDIR64B__"); |
960 | if (HasMOVRS) |
961 | Builder.defineMacro(Name: "__MOVRS__"); |
962 | if (HasPCONFIG) |
963 | Builder.defineMacro(Name: "__PCONFIG__"); |
964 | if (HasPTWRITE) |
965 | Builder.defineMacro(Name: "__PTWRITE__"); |
966 | if (HasINVPCID) |
967 | Builder.defineMacro(Name: "__INVPCID__"); |
968 | if (HasENQCMD) |
969 | Builder.defineMacro(Name: "__ENQCMD__"); |
970 | if (HasHRESET) |
971 | Builder.defineMacro(Name: "__HRESET__"); |
972 | if (HasAMXTILE) |
973 | Builder.defineMacro(Name: "__AMX_TILE__"); |
974 | if (HasAMXINT8) |
975 | Builder.defineMacro(Name: "__AMX_INT8__"); |
976 | if (HasAMXBF16) |
977 | Builder.defineMacro(Name: "__AMX_BF16__"); |
978 | if (HasAMXFP16) |
979 | Builder.defineMacro(Name: "__AMX_FP16__"); |
980 | if (HasAMXCOMPLEX) |
981 | Builder.defineMacro(Name: "__AMX_COMPLEX__"); |
982 | if (HasAMXFP8) |
983 | Builder.defineMacro(Name: "__AMX_FP8__"); |
984 | if (HasAMXMOVRS) |
985 | Builder.defineMacro(Name: "__AMX_MOVRS__"); |
986 | if (HasAMXTRANSPOSE) |
987 | Builder.defineMacro(Name: "__AMX_TRANSPOSE__"); |
988 | if (HasAMXAVX512) |
989 | Builder.defineMacro(Name: "__AMX_AVX512__"); |
990 | if (HasAMXTF32) |
991 | Builder.defineMacro(Name: "__AMX_TF32__"); |
992 | if (HasCMPCCXADD) |
993 | Builder.defineMacro(Name: "__CMPCCXADD__"); |
994 | if (HasRAOINT) |
995 | Builder.defineMacro(Name: "__RAOINT__"); |
996 | if (HasAVXIFMA) |
997 | Builder.defineMacro(Name: "__AVXIFMA__"); |
998 | if (HasAVXNECONVERT) |
999 | Builder.defineMacro(Name: "__AVXNECONVERT__"); |
1000 | if (HasAVXVNNI) |
1001 | Builder.defineMacro(Name: "__AVXVNNI__"); |
1002 | if (HasAVXVNNIINT16) |
1003 | Builder.defineMacro(Name: "__AVXVNNIINT16__"); |
1004 | if (HasAVXVNNIINT8) |
1005 | Builder.defineMacro(Name: "__AVXVNNIINT8__"); |
1006 | if (HasSERIALIZE) |
1007 | Builder.defineMacro(Name: "__SERIALIZE__"); |
1008 | if (HasTSXLDTRK) |
1009 | Builder.defineMacro(Name: "__TSXLDTRK__"); |
1010 | if (HasUINTR) |
1011 | Builder.defineMacro(Name: "__UINTR__"); |
1012 | if (HasUSERMSR) |
1013 | Builder.defineMacro(Name: "__USERMSR__"); |
1014 | if (HasCRC32) |
1015 | Builder.defineMacro(Name: "__CRC32__"); |
1016 | if (HasEGPR) |
1017 | Builder.defineMacro(Name: "__EGPR__"); |
1018 | if (HasPush2Pop2) |
1019 | Builder.defineMacro(Name: "__PUSH2POP2__"); |
1020 | if (HasPPX) |
1021 | Builder.defineMacro(Name: "__PPX__"); |
1022 | if (HasNDD) |
1023 | Builder.defineMacro(Name: "__NDD__"); |
1024 | if (HasCCMP) |
1025 | Builder.defineMacro(Name: "__CCMP__"); |
1026 | if (HasNF) |
1027 | Builder.defineMacro(Name: "__NF__"); |
1028 | if (HasCF) |
1029 | Builder.defineMacro(Name: "__CF__"); |
1030 | if (HasZU) |
1031 | Builder.defineMacro(Name: "__ZU__"); |
1032 | if (HasEGPR && HasPush2Pop2 && HasPPX && HasNDD && HasCCMP && HasNF && |
1033 | HasCF && HasZU) |
1034 | Builder.defineMacro(Name: "__APX_F__"); |
1035 | if (HasEGPR && HasInlineAsmUseGPR32) |
1036 | Builder.defineMacro(Name: "__APX_INLINE_ASM_USE_GPR32__"); |
1037 | |
1038 | // Each case falls through to the previous one here. |
1039 | switch (SSELevel) { |
1040 | case AVX512F: |
1041 | Builder.defineMacro(Name: "__AVX512F__"); |
1042 | [[fallthrough]]; |
1043 | case AVX2: |
1044 | Builder.defineMacro(Name: "__AVX2__"); |
1045 | [[fallthrough]]; |
1046 | case AVX: |
1047 | Builder.defineMacro(Name: "__AVX__"); |
1048 | [[fallthrough]]; |
1049 | case SSE42: |
1050 | Builder.defineMacro(Name: "__SSE4_2__"); |
1051 | [[fallthrough]]; |
1052 | case SSE41: |
1053 | Builder.defineMacro(Name: "__SSE4_1__"); |
1054 | [[fallthrough]]; |
1055 | case SSSE3: |
1056 | Builder.defineMacro(Name: "__SSSE3__"); |
1057 | [[fallthrough]]; |
1058 | case SSE3: |
1059 | Builder.defineMacro(Name: "__SSE3__"); |
1060 | [[fallthrough]]; |
1061 | case SSE2: |
1062 | Builder.defineMacro(Name: "__SSE2__"); |
1063 | Builder.defineMacro(Name: "__SSE2_MATH__"); // -mfp-math=sse always implied. |
1064 | [[fallthrough]]; |
1065 | case SSE1: |
1066 | Builder.defineMacro(Name: "__SSE__"); |
1067 | Builder.defineMacro(Name: "__SSE_MATH__"); // -mfp-math=sse always implied. |
1068 | [[fallthrough]]; |
1069 | case NoSSE: |
1070 | break; |
1071 | } |
1072 | |
1073 | if (Opts.MicrosoftExt && getTriple().getArch() == llvm::Triple::x86) { |
1074 | switch (SSELevel) { |
1075 | case AVX512F: |
1076 | case AVX2: |
1077 | case AVX: |
1078 | case SSE42: |
1079 | case SSE41: |
1080 | case SSSE3: |
1081 | case SSE3: |
1082 | case SSE2: |
1083 | Builder.defineMacro(Name: "_M_IX86_FP", Value: Twine(2)); |
1084 | break; |
1085 | case SSE1: |
1086 | Builder.defineMacro(Name: "_M_IX86_FP", Value: Twine(1)); |
1087 | break; |
1088 | default: |
1089 | Builder.defineMacro(Name: "_M_IX86_FP", Value: Twine(0)); |
1090 | break; |
1091 | } |
1092 | } |
1093 | |
1094 | // Each case falls through to the previous one here. |
1095 | if (HasMMX) { |
1096 | Builder.defineMacro(Name: "__MMX__"); |
1097 | } |
1098 | |
1099 | if (CPU >= CK_i486 || CPU == CK_None) { |
1100 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); |
1101 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); |
1102 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); |
1103 | } |
1104 | if (HasCX8) |
1105 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); |
1106 | if (HasCX16 && getTriple().getArch() == llvm::Triple::x86_64) |
1107 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16"); |
1108 | |
1109 | if (HasFloat128) |
1110 | Builder.defineMacro(Name: "__SIZEOF_FLOAT128__", Value: "16"); |
1111 | |
1112 | if (Opts.CFProtectionReturn || Opts.CFProtectionBranch) |
1113 | Builder.defineMacro(Name: "__CET__", Value: Twine{(Opts.CFProtectionReturn << 1) | |
1114 | Opts.CFProtectionBranch}); |
1115 | } |
1116 | |
1117 | bool X86TargetInfo::isValidFeatureName(StringRef Name) const { |
1118 | return llvm::StringSwitch<bool>(Name) |
1119 | .Case(S: "adx", Value: true) |
1120 | .Case(S: "aes", Value: true) |
1121 | .Case(S: "amx-avx512", Value: true) |
1122 | .Case(S: "amx-bf16", Value: true) |
1123 | .Case(S: "amx-complex", Value: true) |
1124 | .Case(S: "amx-fp16", Value: true) |
1125 | .Case(S: "amx-fp8", Value: true) |
1126 | .Case(S: "amx-int8", Value: true) |
1127 | .Case(S: "amx-movrs", Value: true) |
1128 | .Case(S: "amx-tf32", Value: true) |
1129 | .Case(S: "amx-tile", Value: true) |
1130 | .Case(S: "amx-transpose", Value: true) |
1131 | .Case(S: "avx", Value: true) |
1132 | .Case(S: "avx10.1-256", Value: true) |
1133 | .Case(S: "avx10.1-512", Value: true) |
1134 | .Case(S: "avx10.2-256", Value: true) |
1135 | .Case(S: "avx10.2-512", Value: true) |
1136 | .Case(S: "avx2", Value: true) |
1137 | .Case(S: "avx512f", Value: true) |
1138 | .Case(S: "avx512cd", Value: true) |
1139 | .Case(S: "avx512vpopcntdq", Value: true) |
1140 | .Case(S: "avx512vnni", Value: true) |
1141 | .Case(S: "avx512bf16", Value: true) |
1142 | .Case(S: "avx512fp16", Value: true) |
1143 | .Case(S: "avx512dq", Value: true) |
1144 | .Case(S: "avx512bitalg", Value: true) |
1145 | .Case(S: "avx512bw", Value: true) |
1146 | .Case(S: "avx512vl", Value: true) |
1147 | .Case(S: "avx512vbmi", Value: true) |
1148 | .Case(S: "avx512vbmi2", Value: true) |
1149 | .Case(S: "avx512ifma", Value: true) |
1150 | .Case(S: "avx512vp2intersect", Value: true) |
1151 | .Case(S: "avxifma", Value: true) |
1152 | .Case(S: "avxneconvert", Value: true) |
1153 | .Case(S: "avxvnni", Value: true) |
1154 | .Case(S: "avxvnniint16", Value: true) |
1155 | .Case(S: "avxvnniint8", Value: true) |
1156 | .Case(S: "bmi", Value: true) |
1157 | .Case(S: "bmi2", Value: true) |
1158 | .Case(S: "cldemote", Value: true) |
1159 | .Case(S: "clflushopt", Value: true) |
1160 | .Case(S: "clwb", Value: true) |
1161 | .Case(S: "clzero", Value: true) |
1162 | .Case(S: "cmpccxadd", Value: true) |
1163 | .Case(S: "crc32", Value: true) |
1164 | .Case(S: "cx16", Value: true) |
1165 | .Case(S: "enqcmd", Value: true) |
1166 | .Case(S: "evex512", Value: true) |
1167 | .Case(S: "f16c", Value: true) |
1168 | .Case(S: "fma", Value: true) |
1169 | .Case(S: "fma4", Value: true) |
1170 | .Case(S: "fsgsbase", Value: true) |
1171 | .Case(S: "fxsr", Value: true) |
1172 | .Case(S: "general-regs-only", Value: true) |
1173 | .Case(S: "gfni", Value: true) |
1174 | .Case(S: "hreset", Value: true) |
1175 | .Case(S: "invpcid", Value: true) |
1176 | .Case(S: "kl", Value: true) |
1177 | .Case(S: "widekl", Value: true) |
1178 | .Case(S: "lwp", Value: true) |
1179 | .Case(S: "lzcnt", Value: true) |
1180 | .Case(S: "mmx", Value: true) |
1181 | .Case(S: "movbe", Value: true) |
1182 | .Case(S: "movrs", Value: true) |
1183 | .Case(S: "movdiri", Value: true) |
1184 | .Case(S: "movdir64b", Value: true) |
1185 | .Case(S: "mwaitx", Value: true) |
1186 | .Case(S: "pclmul", Value: true) |
1187 | .Case(S: "pconfig", Value: true) |
1188 | .Case(S: "pku", Value: true) |
1189 | .Case(S: "popcnt", Value: true) |
1190 | .Case(S: "prefer-256-bit", Value: true) |
1191 | .Case(S: "prefetchi", Value: true) |
1192 | .Case(S: "prfchw", Value: true) |
1193 | .Case(S: "ptwrite", Value: true) |
1194 | .Case(S: "raoint", Value: true) |
1195 | .Case(S: "rdpid", Value: true) |
1196 | .Case(S: "rdpru", Value: true) |
1197 | .Case(S: "rdrnd", Value: true) |
1198 | .Case(S: "rdseed", Value: true) |
1199 | .Case(S: "rtm", Value: true) |
1200 | .Case(S: "sahf", Value: true) |
1201 | .Case(S: "serialize", Value: true) |
1202 | .Case(S: "sgx", Value: true) |
1203 | .Case(S: "sha", Value: true) |
1204 | .Case(S: "sha512", Value: true) |
1205 | .Case(S: "shstk", Value: true) |
1206 | .Case(S: "sm3", Value: true) |
1207 | .Case(S: "sm4", Value: true) |
1208 | .Case(S: "sse", Value: true) |
1209 | .Case(S: "sse2", Value: true) |
1210 | .Case(S: "sse3", Value: true) |
1211 | .Case(S: "ssse3", Value: true) |
1212 | .Case(S: "sse4", Value: true) |
1213 | .Case(S: "sse4.1", Value: true) |
1214 | .Case(S: "sse4.2", Value: true) |
1215 | .Case(S: "sse4a", Value: true) |
1216 | .Case(S: "tbm", Value: true) |
1217 | .Case(S: "tsxldtrk", Value: true) |
1218 | .Case(S: "uintr", Value: true) |
1219 | .Case(S: "usermsr", Value: true) |
1220 | .Case(S: "vaes", Value: true) |
1221 | .Case(S: "vpclmulqdq", Value: true) |
1222 | .Case(S: "wbnoinvd", Value: true) |
1223 | .Case(S: "waitpkg", Value: true) |
1224 | .Case(S: "x87", Value: true) |
1225 | .Case(S: "xop", Value: true) |
1226 | .Case(S: "xsave", Value: true) |
1227 | .Case(S: "xsavec", Value: true) |
1228 | .Case(S: "xsaves", Value: true) |
1229 | .Case(S: "xsaveopt", Value: true) |
1230 | .Case(S: "egpr", Value: true) |
1231 | .Case(S: "push2pop2", Value: true) |
1232 | .Case(S: "ppx", Value: true) |
1233 | .Case(S: "ndd", Value: true) |
1234 | .Case(S: "ccmp", Value: true) |
1235 | .Case(S: "nf", Value: true) |
1236 | .Case(S: "cf", Value: true) |
1237 | .Case(S: "zu", Value: true) |
1238 | .Default(Value: false); |
1239 | } |
1240 | |
1241 | bool X86TargetInfo::hasFeature(StringRef Feature) const { |
1242 | return llvm::StringSwitch<bool>(Feature) |
1243 | .Case(S: "adx", Value: HasADX) |
1244 | .Case(S: "aes", Value: HasAES) |
1245 | .Case(S: "amx-avx512", Value: HasAMXAVX512) |
1246 | .Case(S: "amx-bf16", Value: HasAMXBF16) |
1247 | .Case(S: "amx-complex", Value: HasAMXCOMPLEX) |
1248 | .Case(S: "amx-fp16", Value: HasAMXFP16) |
1249 | .Case(S: "amx-fp8", Value: HasAMXFP8) |
1250 | .Case(S: "amx-int8", Value: HasAMXINT8) |
1251 | .Case(S: "amx-movrs", Value: HasAMXMOVRS) |
1252 | .Case(S: "amx-tf32", Value: HasAMXTF32) |
1253 | .Case(S: "amx-tile", Value: HasAMXTILE) |
1254 | .Case(S: "amx-transpose", Value: HasAMXTRANSPOSE) |
1255 | .Case(S: "avx", Value: SSELevel >= AVX) |
1256 | .Case(S: "avx10.1-256", Value: HasAVX10_1) |
1257 | .Case(S: "avx10.1-512", Value: HasAVX10_1_512) |
1258 | .Case(S: "avx10.2-256", Value: HasAVX10_2) |
1259 | .Case(S: "avx10.2-512", Value: HasAVX10_2_512) |
1260 | .Case(S: "avx2", Value: SSELevel >= AVX2) |
1261 | .Case(S: "avx512f", Value: SSELevel >= AVX512F) |
1262 | .Case(S: "avx512cd", Value: HasAVX512CD) |
1263 | .Case(S: "avx512vpopcntdq", Value: HasAVX512VPOPCNTDQ) |
1264 | .Case(S: "avx512vnni", Value: HasAVX512VNNI) |
1265 | .Case(S: "avx512bf16", Value: HasAVX512BF16) |
1266 | .Case(S: "avx512fp16", Value: HasAVX512FP16) |
1267 | .Case(S: "avx512dq", Value: HasAVX512DQ) |
1268 | .Case(S: "avx512bitalg", Value: HasAVX512BITALG) |
1269 | .Case(S: "avx512bw", Value: HasAVX512BW) |
1270 | .Case(S: "avx512vl", Value: HasAVX512VL) |
1271 | .Case(S: "avx512vbmi", Value: HasAVX512VBMI) |
1272 | .Case(S: "avx512vbmi2", Value: HasAVX512VBMI2) |
1273 | .Case(S: "avx512ifma", Value: HasAVX512IFMA) |
1274 | .Case(S: "avx512vp2intersect", Value: HasAVX512VP2INTERSECT) |
1275 | .Case(S: "avxifma", Value: HasAVXIFMA) |
1276 | .Case(S: "avxneconvert", Value: HasAVXNECONVERT) |
1277 | .Case(S: "avxvnni", Value: HasAVXVNNI) |
1278 | .Case(S: "avxvnniint16", Value: HasAVXVNNIINT16) |
1279 | .Case(S: "avxvnniint8", Value: HasAVXVNNIINT8) |
1280 | .Case(S: "bmi", Value: HasBMI) |
1281 | .Case(S: "bmi2", Value: HasBMI2) |
1282 | .Case(S: "cldemote", Value: HasCLDEMOTE) |
1283 | .Case(S: "clflushopt", Value: HasCLFLUSHOPT) |
1284 | .Case(S: "clwb", Value: HasCLWB) |
1285 | .Case(S: "clzero", Value: HasCLZERO) |
1286 | .Case(S: "cmpccxadd", Value: HasCMPCCXADD) |
1287 | .Case(S: "crc32", Value: HasCRC32) |
1288 | .Case(S: "cx8", Value: HasCX8) |
1289 | .Case(S: "cx16", Value: HasCX16) |
1290 | .Case(S: "enqcmd", Value: HasENQCMD) |
1291 | .Case(S: "evex512", Value: HasEVEX512) |
1292 | .Case(S: "f16c", Value: HasF16C) |
1293 | .Case(S: "fma", Value: HasFMA) |
1294 | .Case(S: "fma4", Value: XOPLevel >= FMA4) |
1295 | .Case(S: "fsgsbase", Value: HasFSGSBASE) |
1296 | .Case(S: "fxsr", Value: HasFXSR) |
1297 | .Case(S: "gfni", Value: HasGFNI) |
1298 | .Case(S: "hreset", Value: HasHRESET) |
1299 | .Case(S: "invpcid", Value: HasINVPCID) |
1300 | .Case(S: "kl", Value: HasKL) |
1301 | .Case(S: "widekl", Value: HasWIDEKL) |
1302 | .Case(S: "lwp", Value: HasLWP) |
1303 | .Case(S: "lzcnt", Value: HasLZCNT) |
1304 | .Case(S: "mmx", Value: HasMMX) |
1305 | .Case(S: "movbe", Value: HasMOVBE) |
1306 | .Case(S: "movrs", Value: HasMOVRS) |
1307 | .Case(S: "movdiri", Value: HasMOVDIRI) |
1308 | .Case(S: "movdir64b", Value: HasMOVDIR64B) |
1309 | .Case(S: "mwaitx", Value: HasMWAITX) |
1310 | .Case(S: "pclmul", Value: HasPCLMUL) |
1311 | .Case(S: "pconfig", Value: HasPCONFIG) |
1312 | .Case(S: "pku", Value: HasPKU) |
1313 | .Case(S: "popcnt", Value: HasPOPCNT) |
1314 | .Case(S: "prefetchi", Value: HasPREFETCHI) |
1315 | .Case(S: "prfchw", Value: HasPRFCHW) |
1316 | .Case(S: "ptwrite", Value: HasPTWRITE) |
1317 | .Case(S: "raoint", Value: HasRAOINT) |
1318 | .Case(S: "rdpid", Value: HasRDPID) |
1319 | .Case(S: "rdpru", Value: HasRDPRU) |
1320 | .Case(S: "rdrnd", Value: HasRDRND) |
1321 | .Case(S: "rdseed", Value: HasRDSEED) |
1322 | .Case(S: "retpoline-external-thunk", Value: HasRetpolineExternalThunk) |
1323 | .Case(S: "rtm", Value: HasRTM) |
1324 | .Case(S: "sahf", Value: HasLAHFSAHF) |
1325 | .Case(S: "serialize", Value: HasSERIALIZE) |
1326 | .Case(S: "sgx", Value: HasSGX) |
1327 | .Case(S: "sha", Value: HasSHA) |
1328 | .Case(S: "sha512", Value: HasSHA512) |
1329 | .Case(S: "shstk", Value: HasSHSTK) |
1330 | .Case(S: "sm3", Value: HasSM3) |
1331 | .Case(S: "sm4", Value: HasSM4) |
1332 | .Case(S: "sse", Value: SSELevel >= SSE1) |
1333 | .Case(S: "sse2", Value: SSELevel >= SSE2) |
1334 | .Case(S: "sse3", Value: SSELevel >= SSE3) |
1335 | .Case(S: "ssse3", Value: SSELevel >= SSSE3) |
1336 | .Case(S: "sse4.1", Value: SSELevel >= SSE41) |
1337 | .Case(S: "sse4.2", Value: SSELevel >= SSE42) |
1338 | .Case(S: "sse4a", Value: XOPLevel >= SSE4A) |
1339 | .Case(S: "tbm", Value: HasTBM) |
1340 | .Case(S: "tsxldtrk", Value: HasTSXLDTRK) |
1341 | .Case(S: "uintr", Value: HasUINTR) |
1342 | .Case(S: "usermsr", Value: HasUSERMSR) |
1343 | .Case(S: "vaes", Value: HasVAES) |
1344 | .Case(S: "vpclmulqdq", Value: HasVPCLMULQDQ) |
1345 | .Case(S: "wbnoinvd", Value: HasWBNOINVD) |
1346 | .Case(S: "waitpkg", Value: HasWAITPKG) |
1347 | .Case(S: "x86", Value: true) |
1348 | .Case(S: "x86_32", Value: getTriple().getArch() == llvm::Triple::x86) |
1349 | .Case(S: "x86_64", Value: getTriple().getArch() == llvm::Triple::x86_64) |
1350 | .Case(S: "x87", Value: HasX87) |
1351 | .Case(S: "xop", Value: XOPLevel >= XOP) |
1352 | .Case(S: "xsave", Value: HasXSAVE) |
1353 | .Case(S: "xsavec", Value: HasXSAVEC) |
1354 | .Case(S: "xsaves", Value: HasXSAVES) |
1355 | .Case(S: "xsaveopt", Value: HasXSAVEOPT) |
1356 | .Case(S: "fullbf16", Value: HasFullBFloat16) |
1357 | .Case(S: "egpr", Value: HasEGPR) |
1358 | .Case(S: "push2pop2", Value: HasPush2Pop2) |
1359 | .Case(S: "ppx", Value: HasPPX) |
1360 | .Case(S: "ndd", Value: HasNDD) |
1361 | .Case(S: "ccmp", Value: HasCCMP) |
1362 | .Case(S: "nf", Value: HasNF) |
1363 | .Case(S: "cf", Value: HasCF) |
1364 | .Case(S: "zu", Value: HasZU) |
1365 | .Case(S: "branch-hint", Value: HasBranchHint) |
1366 | .Default(Value: false); |
1367 | } |
1368 | |
1369 | // We can't use a generic validation scheme for the features accepted here |
1370 | // versus subtarget features accepted in the target attribute because the |
1371 | // bitfield structure that's initialized in the runtime only supports the |
1372 | // below currently rather than the full range of subtarget features. (See |
1373 | // X86TargetInfo::hasFeature for a somewhat comprehensive list). |
1374 | bool X86TargetInfo::validateCpuSupports(StringRef FeatureStr) const { |
1375 | return llvm::StringSwitch<bool>(FeatureStr) |
1376 | #define X86_FEATURE_COMPAT(ENUM, STR, PRIORITY) .Case(STR, true) |
1377 | #define X86_MICROARCH_LEVEL(ENUM, STR, PRIORITY) .Case(STR, true) |
1378 | #include "llvm/TargetParser/X86TargetParser.def" |
1379 | .Default(Value: false); |
1380 | } |
1381 | |
1382 | static llvm::X86::ProcessorFeatures getFeature(StringRef Name) { |
1383 | return llvm::StringSwitch<llvm::X86::ProcessorFeatures>(Name) |
1384 | #define X86_FEATURE_COMPAT(ENUM, STR, PRIORITY) \ |
1385 | .Case(STR, llvm::X86::FEATURE_##ENUM) |
1386 | |
1387 | #include "llvm/TargetParser/X86TargetParser.def" |
1388 | ; |
1389 | // Note, this function should only be used after ensuring the value is |
1390 | // correct, so it asserts if the value is out of range. |
1391 | } |
1392 | |
1393 | uint64_t X86TargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const { |
1394 | auto getPriority = [](StringRef Feature) -> uint64_t { |
1395 | // Valid CPUs have a 'key feature' that compares just better than its key |
1396 | // feature. |
1397 | using namespace llvm::X86; |
1398 | CPUKind Kind = parseArchX86(CPU: Feature); |
1399 | if (Kind != CK_None) { |
1400 | ProcessorFeatures KeyFeature = getKeyFeature(Kind); |
1401 | return (getFeaturePriority(Feat: KeyFeature) << 1) + 1; |
1402 | } |
1403 | // Now we know we have a feature, so get its priority and shift it a few so |
1404 | // that we have sufficient room for the CPUs (above). |
1405 | return getFeaturePriority(Feat: getFeature(Name: Feature)) << 1; |
1406 | }; |
1407 | |
1408 | uint64_t Priority = 0; |
1409 | for (StringRef Feature : Features) |
1410 | if (!Feature.empty()) |
1411 | Priority = std::max(a: Priority, b: getPriority(Feature)); |
1412 | return Priority; |
1413 | } |
1414 | |
1415 | bool X86TargetInfo::validateCPUSpecificCPUDispatch(StringRef Name) const { |
1416 | return llvm::X86::validateCPUSpecificCPUDispatch(Name); |
1417 | } |
1418 | |
1419 | char X86TargetInfo::CPUSpecificManglingCharacter(StringRef Name) const { |
1420 | return llvm::X86::getCPUDispatchMangling(Name); |
1421 | } |
1422 | |
1423 | void X86TargetInfo::getCPUSpecificCPUDispatchFeatures( |
1424 | StringRef Name, llvm::SmallVectorImpl<StringRef> &Features) const { |
1425 | SmallVector<StringRef, 32> TargetCPUFeatures; |
1426 | llvm::X86::getFeaturesForCPU(CPU: Name, Features&: TargetCPUFeatures, NeedPlus: true); |
1427 | for (auto &F : TargetCPUFeatures) |
1428 | Features.push_back(Elt: F); |
1429 | } |
1430 | |
1431 | // We can't use a generic validation scheme for the cpus accepted here |
1432 | // versus subtarget cpus accepted in the target attribute because the |
1433 | // variables intitialized by the runtime only support the below currently |
1434 | // rather than the full range of cpus. |
1435 | bool X86TargetInfo::validateCpuIs(StringRef FeatureStr) const { |
1436 | return llvm::StringSwitch<bool>(FeatureStr) |
1437 | #define X86_VENDOR(ENUM, STRING) .Case(STRING, true) |
1438 | #define X86_CPU_TYPE_ALIAS(ENUM, ALIAS) .Case(ALIAS, true) |
1439 | #define X86_CPU_TYPE(ENUM, STR) .Case(STR, true) |
1440 | #define X86_CPU_SUBTYPE_ALIAS(ENUM, ALIAS) .Case(ALIAS, true) |
1441 | #define X86_CPU_SUBTYPE(ENUM, STR) .Case(STR, true) |
1442 | #include "llvm/TargetParser/X86TargetParser.def" |
1443 | .Default(Value: false); |
1444 | } |
1445 | |
1446 | static unsigned matchAsmCCConstraint(const char *Name) { |
1447 | auto RV = llvm::StringSwitch<unsigned>(Name) |
1448 | .Case(S: "@cca", Value: 4) |
1449 | .Case(S: "@ccae", Value: 5) |
1450 | .Case(S: "@ccb", Value: 4) |
1451 | .Case(S: "@ccbe", Value: 5) |
1452 | .Case(S: "@ccc", Value: 4) |
1453 | .Case(S: "@cce", Value: 4) |
1454 | .Case(S: "@ccz", Value: 4) |
1455 | .Case(S: "@ccg", Value: 4) |
1456 | .Case(S: "@ccge", Value: 5) |
1457 | .Case(S: "@ccl", Value: 4) |
1458 | .Case(S: "@ccle", Value: 5) |
1459 | .Case(S: "@ccna", Value: 5) |
1460 | .Case(S: "@ccnae", Value: 6) |
1461 | .Case(S: "@ccnb", Value: 5) |
1462 | .Case(S: "@ccnbe", Value: 6) |
1463 | .Case(S: "@ccnc", Value: 5) |
1464 | .Case(S: "@ccne", Value: 5) |
1465 | .Case(S: "@ccnz", Value: 5) |
1466 | .Case(S: "@ccng", Value: 5) |
1467 | .Case(S: "@ccnge", Value: 6) |
1468 | .Case(S: "@ccnl", Value: 5) |
1469 | .Case(S: "@ccnle", Value: 6) |
1470 | .Case(S: "@ccno", Value: 5) |
1471 | .Case(S: "@ccnp", Value: 5) |
1472 | .Case(S: "@ccns", Value: 5) |
1473 | .Case(S: "@cco", Value: 4) |
1474 | .Case(S: "@ccp", Value: 4) |
1475 | .Case(S: "@ccs", Value: 4) |
1476 | .Default(Value: 0); |
1477 | return RV; |
1478 | } |
1479 | |
1480 | bool X86TargetInfo::validateAsmConstraint( |
1481 | const char *&Name, TargetInfo::ConstraintInfo &Info) const { |
1482 | switch (*Name) { |
1483 | default: |
1484 | return false; |
1485 | // Constant constraints. |
1486 | case 'e': // 32-bit signed integer constant for use with sign-extending x86_64 |
1487 | // instructions. |
1488 | case 'Z': // 32-bit unsigned integer constant for use with zero-extending |
1489 | // x86_64 instructions. |
1490 | case 's': |
1491 | Info.setRequiresImmediate(); |
1492 | return true; |
1493 | case 'I': |
1494 | Info.setRequiresImmediate(Min: 0, Max: 31); |
1495 | return true; |
1496 | case 'J': |
1497 | Info.setRequiresImmediate(Min: 0, Max: 63); |
1498 | return true; |
1499 | case 'K': |
1500 | Info.setRequiresImmediate(Min: -128, Max: 127); |
1501 | return true; |
1502 | case 'L': |
1503 | Info.setRequiresImmediate({int(0xff), int(0xffff), int(0xffffffff)}); |
1504 | return true; |
1505 | case 'M': |
1506 | Info.setRequiresImmediate(Min: 0, Max: 3); |
1507 | return true; |
1508 | case 'N': |
1509 | Info.setRequiresImmediate(Min: 0, Max: 255); |
1510 | return true; |
1511 | case 'O': |
1512 | Info.setRequiresImmediate(Min: 0, Max: 127); |
1513 | return true; |
1514 | case 'W': |
1515 | switch (*++Name) { |
1516 | default: |
1517 | return false; |
1518 | case 's': |
1519 | Info.setAllowsRegister(); |
1520 | return true; |
1521 | } |
1522 | // Register constraints. |
1523 | case 'Y': // 'Y' is the first character for several 2-character constraints. |
1524 | // Shift the pointer to the second character of the constraint. |
1525 | Name++; |
1526 | switch (*Name) { |
1527 | default: |
1528 | return false; |
1529 | case 'z': // First SSE register. |
1530 | case '2': |
1531 | case 't': // Any SSE register, when SSE2 is enabled. |
1532 | case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled. |
1533 | case 'm': // Any MMX register, when inter-unit moves enabled. |
1534 | case 'k': // AVX512 arch mask registers: k1-k7. |
1535 | Info.setAllowsRegister(); |
1536 | return true; |
1537 | } |
1538 | case 'f': // Any x87 floating point stack register. |
1539 | // Constraint 'f' cannot be used for output operands. |
1540 | if (Info.ConstraintStr[0] == '=' || Info.ConstraintStr[0] == '+') |
1541 | return false; |
1542 | Info.setAllowsRegister(); |
1543 | return true; |
1544 | case 'a': // eax. |
1545 | case 'b': // ebx. |
1546 | case 'c': // ecx. |
1547 | case 'd': // edx. |
1548 | case 'S': // esi. |
1549 | case 'D': // edi. |
1550 | case 'A': // edx:eax. |
1551 | case 't': // Top of floating point stack. |
1552 | case 'u': // Second from top of floating point stack. |
1553 | case 'q': // Any register accessible as [r]l: a, b, c, and d. |
1554 | case 'y': // Any MMX register. |
1555 | case 'v': // Any {X,Y,Z}MM register (Arch & context dependent) |
1556 | case 'x': // Any SSE register. |
1557 | case 'k': // Any AVX512 mask register (same as Yk, additionally allows k0 |
1558 | // for intermideate k reg operations). |
1559 | case 'Q': // Any register accessible as [r]h: a, b, c, and d. |
1560 | case 'R': // "Legacy" registers: ax, bx, cx, dx, di, si, sp, bp. |
1561 | case 'l': // "Index" registers: any general register that can be used as an |
1562 | // index in a base+index memory access. |
1563 | Info.setAllowsRegister(); |
1564 | return true; |
1565 | // Floating point constant constraints. |
1566 | case 'C': // SSE floating point constant. |
1567 | case 'G': // x87 floating point constant. |
1568 | return true; |
1569 | case 'j': |
1570 | Name++; |
1571 | switch (*Name) { |
1572 | default: |
1573 | return false; |
1574 | case 'r': |
1575 | Info.setAllowsRegister(); |
1576 | return true; |
1577 | case 'R': |
1578 | Info.setAllowsRegister(); |
1579 | return true; |
1580 | } |
1581 | case '@': |
1582 | // CC condition changes. |
1583 | if (auto Len = matchAsmCCConstraint(Name)) { |
1584 | Name += Len - 1; |
1585 | Info.setAllowsRegister(); |
1586 | return true; |
1587 | } |
1588 | return false; |
1589 | } |
1590 | } |
1591 | |
1592 | // Below is based on the following information: |
1593 | // +------------------------------------+-------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ |
1594 | // | Processor Name | Cache Line Size (Bytes) | Source | |
1595 | // +------------------------------------+-------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ |
1596 | // | i386 | 64 | https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf | |
1597 | // | i486 | 16 | "four doublewords" (doubleword = 32 bits, 4 bits * 32 bits = 16 bytes) https://en.wikichip.org/w/images/d/d3/i486_MICROPROCESSOR_HARDWARE_REFERENCE_MANUAL_%281990%29.pdf and http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.126.4216&rep=rep1&type=pdf (page 29) | |
1598 | // | i586/Pentium MMX | 32 | https://www.7-cpu.com/cpu/P-MMX.html | |
1599 | // | i686/Pentium | 32 | https://www.7-cpu.com/cpu/P6.html | |
1600 | // | Netburst/Pentium4 | 64 | https://www.7-cpu.com/cpu/P4-180.html | |
1601 | // | Atom | 64 | https://www.7-cpu.com/cpu/Atom.html | |
1602 | // | Westmere | 64 | https://en.wikichip.org/wiki/intel/microarchitectures/sandy_bridge_(client) "Cache Architecture" | |
1603 | // | Sandy Bridge | 64 | https://en.wikipedia.org/wiki/Sandy_Bridge and https://www.7-cpu.com/cpu/SandyBridge.html | |
1604 | // | Ivy Bridge | 64 | https://blog.stuffedcow.net/2013/01/ivb-cache-replacement/ and https://www.7-cpu.com/cpu/IvyBridge.html | |
1605 | // | Haswell | 64 | https://www.7-cpu.com/cpu/Haswell.html | |
1606 | // | Broadwell | 64 | https://www.7-cpu.com/cpu/Broadwell.html | |
1607 | // | Skylake (including skylake-avx512) | 64 | https://www.nas.nasa.gov/hecc/support/kb/skylake-processors_550.html "Cache Hierarchy" | |
1608 | // | Cascade Lake | 64 | https://www.nas.nasa.gov/hecc/support/kb/cascade-lake-processors_579.html "Cache Hierarchy" | |
1609 | // | Skylake | 64 | https://en.wikichip.org/wiki/intel/microarchitectures/kaby_lake "Memory Hierarchy" | |
1610 | // | Ice Lake | 64 | https://www.7-cpu.com/cpu/Ice_Lake.html | |
1611 | // | Knights Landing | 64 | https://software.intel.com/en-us/articles/intel-xeon-phi-processor-7200-family-memory-management-optimizations "The Intel® Xeon Phi™ Processor Architecture" | |
1612 | // | Knights Mill | 64 | https://software.intel.com/sites/default/files/managed/9e/bc/64-ia-32-architectures-optimization-manual.pdf?countrylabel=Colombia "2.5.5.2 L1 DCache " | |
1613 | // +------------------------------------+-------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ |
1614 | std::optional<unsigned> X86TargetInfo::getCPUCacheLineSize() const { |
1615 | using namespace llvm::X86; |
1616 | switch (CPU) { |
1617 | // i386 |
1618 | case CK_i386: |
1619 | // i486 |
1620 | case CK_i486: |
1621 | case CK_WinChipC6: |
1622 | case CK_WinChip2: |
1623 | case CK_C3: |
1624 | // Lakemont |
1625 | case CK_Lakemont: |
1626 | return 16; |
1627 | |
1628 | // i586 |
1629 | case CK_i586: |
1630 | case CK_Pentium: |
1631 | case CK_PentiumMMX: |
1632 | // i686 |
1633 | case CK_PentiumPro: |
1634 | case CK_i686: |
1635 | case CK_Pentium2: |
1636 | case CK_Pentium3: |
1637 | case CK_PentiumM: |
1638 | case CK_C3_2: |
1639 | // K6 |
1640 | case CK_K6: |
1641 | case CK_K6_2: |
1642 | case CK_K6_3: |
1643 | // Geode |
1644 | case CK_Geode: |
1645 | return 32; |
1646 | |
1647 | // Netburst |
1648 | case CK_Pentium4: |
1649 | case CK_Prescott: |
1650 | case CK_Nocona: |
1651 | // Atom |
1652 | case CK_Bonnell: |
1653 | case CK_Silvermont: |
1654 | case CK_Goldmont: |
1655 | case CK_GoldmontPlus: |
1656 | case CK_Tremont: |
1657 | case CK_Gracemont: |
1658 | |
1659 | case CK_Westmere: |
1660 | case CK_SandyBridge: |
1661 | case CK_IvyBridge: |
1662 | case CK_Haswell: |
1663 | case CK_Broadwell: |
1664 | case CK_SkylakeClient: |
1665 | case CK_SkylakeServer: |
1666 | case CK_Cascadelake: |
1667 | case CK_Nehalem: |
1668 | case CK_Cooperlake: |
1669 | case CK_Cannonlake: |
1670 | case CK_Tigerlake: |
1671 | case CK_SapphireRapids: |
1672 | case CK_IcelakeClient: |
1673 | case CK_Rocketlake: |
1674 | case CK_IcelakeServer: |
1675 | case CK_Alderlake: |
1676 | case CK_Raptorlake: |
1677 | case CK_Meteorlake: |
1678 | case CK_Arrowlake: |
1679 | case CK_ArrowlakeS: |
1680 | case CK_Lunarlake: |
1681 | case CK_Pantherlake: |
1682 | case CK_Sierraforest: |
1683 | case CK_Grandridge: |
1684 | case CK_Graniterapids: |
1685 | case CK_GraniterapidsD: |
1686 | case CK_Emeraldrapids: |
1687 | case CK_Clearwaterforest: |
1688 | case CK_Diamondrapids: |
1689 | case CK_KNL: |
1690 | case CK_KNM: |
1691 | // K7 |
1692 | case CK_Athlon: |
1693 | case CK_AthlonXP: |
1694 | // K8 |
1695 | case CK_K8: |
1696 | case CK_K8SSE3: |
1697 | case CK_AMDFAM10: |
1698 | // Bobcat |
1699 | case CK_BTVER1: |
1700 | case CK_BTVER2: |
1701 | // Bulldozer |
1702 | case CK_BDVER1: |
1703 | case CK_BDVER2: |
1704 | case CK_BDVER3: |
1705 | case CK_BDVER4: |
1706 | // Zen |
1707 | case CK_ZNVER1: |
1708 | case CK_ZNVER2: |
1709 | case CK_ZNVER3: |
1710 | case CK_ZNVER4: |
1711 | case CK_ZNVER5: |
1712 | // Deprecated |
1713 | case CK_x86_64: |
1714 | case CK_x86_64_v2: |
1715 | case CK_x86_64_v3: |
1716 | case CK_x86_64_v4: |
1717 | case CK_Yonah: |
1718 | case CK_Penryn: |
1719 | case CK_Core2: |
1720 | return 64; |
1721 | |
1722 | // The following currently have unknown cache line sizes (but they are probably all 64): |
1723 | // Core |
1724 | case CK_None: |
1725 | return std::nullopt; |
1726 | } |
1727 | llvm_unreachable("Unknown CPU kind"); |
1728 | } |
1729 | |
1730 | bool X86TargetInfo::validateOutputSize(const llvm::StringMap<bool> &FeatureMap, |
1731 | StringRef Constraint, |
1732 | unsigned Size) const { |
1733 | // Strip off constraint modifiers. |
1734 | Constraint = Constraint.ltrim(Chars: "=+&"); |
1735 | |
1736 | return validateOperandSize(FeatureMap, Constraint, Size); |
1737 | } |
1738 | |
1739 | bool X86TargetInfo::validateInputSize(const llvm::StringMap<bool> &FeatureMap, |
1740 | StringRef Constraint, |
1741 | unsigned Size) const { |
1742 | return validateOperandSize(FeatureMap, Constraint, Size); |
1743 | } |
1744 | |
1745 | bool X86TargetInfo::validateOperandSize(const llvm::StringMap<bool> &FeatureMap, |
1746 | StringRef Constraint, |
1747 | unsigned Size) const { |
1748 | switch (Constraint[0]) { |
1749 | default: |
1750 | break; |
1751 | case 'k': |
1752 | // Registers k0-k7 (AVX512) size limit is 64 bit. |
1753 | case 'y': |
1754 | return Size <= 64; |
1755 | case 'f': |
1756 | case 't': |
1757 | case 'u': |
1758 | return Size <= 128; |
1759 | case 'Y': |
1760 | // 'Y' is the first character for several 2-character constraints. |
1761 | switch (Constraint[1]) { |
1762 | default: |
1763 | return false; |
1764 | case 'm': |
1765 | // 'Ym' is synonymous with 'y'. |
1766 | case 'k': |
1767 | return Size <= 64; |
1768 | case 'z': |
1769 | // XMM0/YMM/ZMM0 |
1770 | if (hasFeatureEnabled(Features: FeatureMap, Name: "avx512f") && |
1771 | hasFeatureEnabled(Features: FeatureMap, Name: "evex512")) |
1772 | // ZMM0 can be used if target supports AVX512F and EVEX512 is set. |
1773 | return Size <= 512U; |
1774 | else if (hasFeatureEnabled(Features: FeatureMap, Name: "avx")) |
1775 | // YMM0 can be used if target supports AVX. |
1776 | return Size <= 256U; |
1777 | else if (hasFeatureEnabled(Features: FeatureMap, Name: "sse")) |
1778 | return Size <= 128U; |
1779 | return false; |
1780 | case 'i': |
1781 | case 't': |
1782 | case '2': |
1783 | // 'Yi','Yt','Y2' are synonymous with 'x' when SSE2 is enabled. |
1784 | if (SSELevel < SSE2) |
1785 | return false; |
1786 | break; |
1787 | } |
1788 | break; |
1789 | case 'v': |
1790 | case 'x': |
1791 | if (hasFeatureEnabled(Features: FeatureMap, Name: "avx512f") && |
1792 | hasFeatureEnabled(Features: FeatureMap, Name: "evex512")) |
1793 | // 512-bit zmm registers can be used if target supports AVX512F and |
1794 | // EVEX512 is set. |
1795 | return Size <= 512U; |
1796 | else if (hasFeatureEnabled(Features: FeatureMap, Name: "avx")) |
1797 | // 256-bit ymm registers can be used if target supports AVX. |
1798 | return Size <= 256U; |
1799 | return Size <= 128U; |
1800 | |
1801 | } |
1802 | |
1803 | return true; |
1804 | } |
1805 | |
1806 | std::string X86TargetInfo::convertConstraint(const char *&Constraint) const { |
1807 | switch (*Constraint) { |
1808 | case '@': |
1809 | if (auto Len = matchAsmCCConstraint(Name: Constraint)) { |
1810 | std::string Converted = "{"+ std::string(Constraint, Len) + "}"; |
1811 | Constraint += Len - 1; |
1812 | return Converted; |
1813 | } |
1814 | return std::string(1, *Constraint); |
1815 | case 'a': |
1816 | return std::string("{ax}"); |
1817 | case 'b': |
1818 | return std::string("{bx}"); |
1819 | case 'c': |
1820 | return std::string("{cx}"); |
1821 | case 'd': |
1822 | return std::string("{dx}"); |
1823 | case 'S': |
1824 | return std::string("{si}"); |
1825 | case 'D': |
1826 | return std::string("{di}"); |
1827 | case 'p': // Keep 'p' constraint (address). |
1828 | return std::string("p"); |
1829 | case 't': // top of floating point stack. |
1830 | return std::string("{st}"); |
1831 | case 'u': // second from top of floating point stack. |
1832 | return std::string("{st(1)}"); // second from top of floating point stack. |
1833 | case 'W': |
1834 | assert(Constraint[1] == 's'); |
1835 | return '^' + std::string(Constraint++, 2); |
1836 | case 'Y': |
1837 | switch (Constraint[1]) { |
1838 | default: |
1839 | // Break from inner switch and fall through (copy single char), |
1840 | // continue parsing after copying the current constraint into |
1841 | // the return string. |
1842 | break; |
1843 | case 'k': |
1844 | case 'm': |
1845 | case 'i': |
1846 | case 't': |
1847 | case 'z': |
1848 | case '2': |
1849 | // "^" hints llvm that this is a 2 letter constraint. |
1850 | // "Constraint++" is used to promote the string iterator |
1851 | // to the next constraint. |
1852 | return std::string("^") + std::string(Constraint++, 2); |
1853 | } |
1854 | [[fallthrough]]; |
1855 | case 'j': |
1856 | switch (Constraint[1]) { |
1857 | default: |
1858 | // Break from inner switch and fall through (copy single char), |
1859 | // continue parsing after copying the current constraint into |
1860 | // the return string. |
1861 | break; |
1862 | case 'r': |
1863 | case 'R': |
1864 | // "^" hints llvm that this is a 2 letter constraint. |
1865 | // "Constraint++" is used to promote the string iterator |
1866 | // to the next constraint. |
1867 | return std::string("^") + std::string(Constraint++, 2); |
1868 | } |
1869 | [[fallthrough]]; |
1870 | default: |
1871 | return std::string(1, *Constraint); |
1872 | } |
1873 | } |
1874 | |
1875 | void X86TargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const { |
1876 | bool Only64Bit = getTriple().getArch() != llvm::Triple::x86; |
1877 | llvm::X86::fillValidCPUArchList(Values, Only64Bit); |
1878 | } |
1879 | |
1880 | void X86TargetInfo::fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const { |
1881 | llvm::X86::fillValidTuneCPUList(Values); |
1882 | } |
1883 | |
1884 | ArrayRef<const char *> X86TargetInfo::getGCCRegNames() const { |
1885 | return llvm::ArrayRef(GCCRegNames); |
1886 | } |
1887 | |
1888 | ArrayRef<TargetInfo::AddlRegName> X86TargetInfo::getGCCAddlRegNames() const { |
1889 | return llvm::ArrayRef(AddlRegNames); |
1890 | } |
1891 | |
1892 | llvm::SmallVector<Builtin::InfosShard> |
1893 | X86_32TargetInfo::getTargetBuiltins() const { |
1894 | return { |
1895 | {&X86::BuiltinStrings, X86::BuiltinInfos}, |
1896 | {&X86::BuiltinStrings, X86::PrefixedBuiltinInfos, "__builtin_ia32_"}, |
1897 | }; |
1898 | } |
1899 | |
1900 | llvm::SmallVector<Builtin::InfosShard> |
1901 | X86_64TargetInfo::getTargetBuiltins() const { |
1902 | return { |
1903 | {&X86::BuiltinStrings, X86::BuiltinInfos}, |
1904 | {&X86::BuiltinStrings, X86::PrefixedBuiltinInfos, "__builtin_ia32_"}, |
1905 | {&X86_64::BuiltinStrings, X86_64::BuiltinInfos}, |
1906 | {&X86_64::BuiltinStrings, X86_64::PrefixedBuiltinInfos, |
1907 | "__builtin_ia32_"}, |
1908 | }; |
1909 | } |
1910 |
Definitions
- NumX86Builtins
- NumX86_64Builtins
- NumBuiltins
- BuiltinInfos
- PrefixedBuiltinInfos
- BuiltinInfos
- PrefixedBuiltinInfos
- GCCRegNames
- AddlRegNames
- setFPMath
- initFeatureMap
- setFeatureEnabled
- handleTargetFeatures
- getTargetDefines
- isValidFeatureName
- hasFeature
- validateCpuSupports
- getFeature
- getFMVPriority
- validateCPUSpecificCPUDispatch
- CPUSpecificManglingCharacter
- getCPUSpecificCPUDispatchFeatures
- validateCpuIs
- matchAsmCCConstraint
- validateAsmConstraint
- getCPUCacheLineSize
- validateOutputSize
- validateInputSize
- validateOperandSize
- convertConstraint
- fillValidCPUList
- fillValidTuneCPUList
- getGCCRegNames
- getGCCAddlRegNames
- getTargetBuiltins
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more