| 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(DiagID: 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(DiagID: 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(DiagID: 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 | {.Strings: &X86::BuiltinStrings, .Infos: X86::BuiltinInfos}, |
| 1896 | {.Strings: &X86::BuiltinStrings, .Infos: X86::PrefixedBuiltinInfos, .NamePrefix: "__builtin_ia32_" }, |
| 1897 | }; |
| 1898 | } |
| 1899 | |
| 1900 | llvm::SmallVector<Builtin::InfosShard> |
| 1901 | X86_64TargetInfo::getTargetBuiltins() const { |
| 1902 | return { |
| 1903 | {.Strings: &X86::BuiltinStrings, .Infos: X86::BuiltinInfos}, |
| 1904 | {.Strings: &X86::BuiltinStrings, .Infos: X86::PrefixedBuiltinInfos, .NamePrefix: "__builtin_ia32_" }, |
| 1905 | {.Strings: &X86_64::BuiltinStrings, .Infos: X86_64::BuiltinInfos}, |
| 1906 | {.Strings: &X86_64::BuiltinStrings, .Infos: X86_64::PrefixedBuiltinInfos, |
| 1907 | .NamePrefix: "__builtin_ia32_" }, |
| 1908 | }; |
| 1909 | } |
| 1910 | |