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