summaryrefslogtreecommitdiff
path: root/lib/Basic/Targets/X86.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Basic/Targets/X86.cpp')
-rw-r--r--lib/Basic/Targets/X86.cpp1518
1 files changed, 1518 insertions, 0 deletions
diff --git a/lib/Basic/Targets/X86.cpp b/lib/Basic/Targets/X86.cpp
new file mode 100644
index 0000000000000..7fd9fd0478181
--- /dev/null
+++ b/lib/Basic/Targets/X86.cpp
@@ -0,0 +1,1518 @@
+//===--- X86.cpp - Implement X86 target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements X86 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+
+namespace clang {
+namespace targets {
+
+const Builtin::Info BuiltinInfoX86[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
+ {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
+#include "clang/Basic/BuiltinsX86.def"
+
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
+ {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
+#include "clang/Basic/BuiltinsX86_64.def"
+};
+
+static const char *const GCCRegNames[] = {
+ "ax", "dx", "cx", "bx", "si", "di", "bp", "sp",
+ "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)",
+ "argp", "flags", "fpcr", "fpsr", "dirflag", "frame", "xmm0", "xmm1",
+ "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "mm0", "mm1",
+ "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", "r8", "r9",
+ "r10", "r11", "r12", "r13", "r14", "r15", "xmm8", "xmm9",
+ "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "ymm0", "ymm1",
+ "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9",
+ "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", "xmm16", "xmm17",
+ "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23", "xmm24", "xmm25",
+ "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31", "ymm16", "ymm17",
+ "ymm18", "ymm19", "ymm20", "ymm21", "ymm22", "ymm23", "ymm24", "ymm25",
+ "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31", "zmm0", "zmm1",
+ "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9",
+ "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17",
+ "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25",
+ "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "k0", "k1",
+ "k2", "k3", "k4", "k5", "k6", "k7",
+ "cr0", "cr2", "cr3", "cr4", "cr8",
+ "dr0", "dr1", "dr2", "dr3", "dr6", "dr7",
+ "bnd0", "bnd1", "bnd2", "bnd3",
+};
+
+const TargetInfo::AddlRegName AddlRegNames[] = {
+ {{"al", "ah", "eax", "rax"}, 0},
+ {{"bl", "bh", "ebx", "rbx"}, 3},
+ {{"cl", "ch", "ecx", "rcx"}, 2},
+ {{"dl", "dh", "edx", "rdx"}, 1},
+ {{"esi", "rsi"}, 4},
+ {{"edi", "rdi"}, 5},
+ {{"esp", "rsp"}, 7},
+ {{"ebp", "rbp"}, 6},
+ {{"r8d", "r8w", "r8b"}, 38},
+ {{"r9d", "r9w", "r9b"}, 39},
+ {{"r10d", "r10w", "r10b"}, 40},
+ {{"r11d", "r11w", "r11b"}, 41},
+ {{"r12d", "r12w", "r12b"}, 42},
+ {{"r13d", "r13w", "r13b"}, 43},
+ {{"r14d", "r14w", "r14b"}, 44},
+ {{"r15d", "r15w", "r15b"}, 45},
+};
+
+} // namespace targets
+} // namespace clang
+
+using namespace clang;
+using namespace clang::targets;
+
+bool X86TargetInfo::setFPMath(StringRef Name) {
+ if (Name == "387") {
+ FPMath = FP_387;
+ return true;
+ }
+ if (Name == "sse") {
+ FPMath = FP_SSE;
+ return true;
+ }
+ return false;
+}
+
+bool X86TargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
+ // FIXME: This *really* should not be here.
+ // X86_64 always has SSE2.
+ if (getTriple().getArch() == llvm::Triple::x86_64)
+ setFeatureEnabledImpl(Features, "sse2", true);
+
+ const CPUKind Kind = getCPUKind(CPU);
+
+ // Enable X87 for all X86 processors but Lakemont.
+ if (Kind != CK_Lakemont)
+ setFeatureEnabledImpl(Features, "x87", true);
+
+ switch (Kind) {
+ case CK_Generic:
+ case CK_i386:
+ case CK_i486:
+ case CK_i586:
+ case CK_Pentium:
+ case CK_PentiumPro:
+ case CK_Lakemont:
+ break;
+
+ case CK_PentiumMMX:
+ case CK_Pentium2:
+ case CK_K6:
+ case CK_WinChipC6:
+ setFeatureEnabledImpl(Features, "mmx", true);
+ break;
+
+ case CK_Icelake:
+ // TODO: Add icelake features here.
+ LLVM_FALLTHROUGH;
+ case CK_Cannonlake:
+ setFeatureEnabledImpl(Features, "avx512ifma", true);
+ setFeatureEnabledImpl(Features, "avx512vbmi", true);
+ setFeatureEnabledImpl(Features, "sha", true);
+ LLVM_FALLTHROUGH;
+ case CK_SkylakeServer:
+ setFeatureEnabledImpl(Features, "avx512f", true);
+ setFeatureEnabledImpl(Features, "avx512cd", true);
+ setFeatureEnabledImpl(Features, "avx512dq", true);
+ setFeatureEnabledImpl(Features, "avx512bw", true);
+ setFeatureEnabledImpl(Features, "avx512vl", true);
+ setFeatureEnabledImpl(Features, "pku", true);
+ setFeatureEnabledImpl(Features, "clwb", true);
+ LLVM_FALLTHROUGH;
+ case CK_SkylakeClient:
+ setFeatureEnabledImpl(Features, "xsavec", true);
+ setFeatureEnabledImpl(Features, "xsaves", true);
+ setFeatureEnabledImpl(Features, "mpx", true);
+ setFeatureEnabledImpl(Features, "sgx", true);
+ setFeatureEnabledImpl(Features, "clflushopt", true);
+ setFeatureEnabledImpl(Features, "rtm", true);
+ LLVM_FALLTHROUGH;
+ case CK_Broadwell:
+ setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "adx", true);
+ LLVM_FALLTHROUGH;
+ case CK_Haswell:
+ setFeatureEnabledImpl(Features, "avx2", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "bmi2", true);
+ setFeatureEnabledImpl(Features, "fma", true);
+ setFeatureEnabledImpl(Features, "movbe", true);
+ LLVM_FALLTHROUGH;
+ case CK_IvyBridge:
+ setFeatureEnabledImpl(Features, "rdrnd", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ LLVM_FALLTHROUGH;
+ case CK_SandyBridge:
+ setFeatureEnabledImpl(Features, "avx", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ LLVM_FALLTHROUGH;
+ case CK_Westmere:
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ LLVM_FALLTHROUGH;
+ case CK_Nehalem:
+ setFeatureEnabledImpl(Features, "sse4.2", true);
+ LLVM_FALLTHROUGH;
+ case CK_Penryn:
+ setFeatureEnabledImpl(Features, "sse4.1", true);
+ LLVM_FALLTHROUGH;
+ case CK_Core2:
+ setFeatureEnabledImpl(Features, "ssse3", true);
+ LLVM_FALLTHROUGH;
+ case CK_Yonah:
+ case CK_Prescott:
+ case CK_Nocona:
+ setFeatureEnabledImpl(Features, "sse3", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ LLVM_FALLTHROUGH;
+ case CK_PentiumM:
+ case CK_Pentium4:
+ case CK_x86_64:
+ setFeatureEnabledImpl(Features, "sse2", true);
+ LLVM_FALLTHROUGH;
+ case CK_Pentium3:
+ case CK_C3_2:
+ setFeatureEnabledImpl(Features, "sse", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ break;
+
+ case CK_Goldmont:
+ setFeatureEnabledImpl(Features, "sha", true);
+ setFeatureEnabledImpl(Features, "rdrnd", true);
+ setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "xsavec", true);
+ setFeatureEnabledImpl(Features, "xsaves", true);
+ setFeatureEnabledImpl(Features, "clflushopt", true);
+ setFeatureEnabledImpl(Features, "mpx", true);
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ LLVM_FALLTHROUGH;
+ case CK_Silvermont:
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "sse4.2", true);
+ LLVM_FALLTHROUGH;
+ case CK_Bonnell:
+ setFeatureEnabledImpl(Features, "movbe", true);
+ setFeatureEnabledImpl(Features, "ssse3", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ break;
+
+ case CK_KNM:
+ // TODO: Add avx5124fmaps/avx5124vnniw.
+ setFeatureEnabledImpl(Features, "avx512vpopcntdq", true);
+ LLVM_FALLTHROUGH;
+ case CK_KNL:
+ setFeatureEnabledImpl(Features, "avx512f", true);
+ setFeatureEnabledImpl(Features, "avx512cd", true);
+ setFeatureEnabledImpl(Features, "avx512er", true);
+ setFeatureEnabledImpl(Features, "avx512pf", true);
+ setFeatureEnabledImpl(Features, "prefetchwt1", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "adx", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "bmi2", true);
+ setFeatureEnabledImpl(Features, "rtm", true);
+ setFeatureEnabledImpl(Features, "fma", true);
+ setFeatureEnabledImpl(Features, "rdrnd", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "movbe", true);
+ break;
+
+ case CK_K6_2:
+ case CK_K6_3:
+ case CK_WinChip2:
+ case CK_C3:
+ setFeatureEnabledImpl(Features, "3dnow", true);
+ break;
+
+ case CK_AMDFAM10:
+ setFeatureEnabledImpl(Features, "sse4a", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "popcnt", true);
+ LLVM_FALLTHROUGH;
+ case CK_K8SSE3:
+ setFeatureEnabledImpl(Features, "sse3", true);
+ LLVM_FALLTHROUGH;
+ case CK_K8:
+ setFeatureEnabledImpl(Features, "sse2", true);
+ LLVM_FALLTHROUGH;
+ case CK_AthlonXP:
+ setFeatureEnabledImpl(Features, "sse", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ LLVM_FALLTHROUGH;
+ case CK_Athlon:
+ case CK_Geode:
+ setFeatureEnabledImpl(Features, "3dnowa", true);
+ break;
+
+ case CK_BTVER2:
+ setFeatureEnabledImpl(Features, "avx", true);
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "movbe", true);
+ LLVM_FALLTHROUGH;
+ case CK_BTVER1:
+ setFeatureEnabledImpl(Features, "ssse3", true);
+ setFeatureEnabledImpl(Features, "sse4a", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "popcnt", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ break;
+
+ case CK_ZNVER1:
+ setFeatureEnabledImpl(Features, "adx", true);
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "avx2", true);
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "bmi2", true);
+ setFeatureEnabledImpl(Features, "clflushopt", true);
+ setFeatureEnabledImpl(Features, "clzero", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "fma", true);
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "mwaitx", true);
+ setFeatureEnabledImpl(Features, "movbe", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "popcnt", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
+ setFeatureEnabledImpl(Features, "rdrnd", true);
+ setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "sha", true);
+ setFeatureEnabledImpl(Features, "sse4a", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "xsavec", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "xsaves", true);
+ break;
+
+ case CK_BDVER4:
+ setFeatureEnabledImpl(Features, "avx2", true);
+ setFeatureEnabledImpl(Features, "bmi2", true);
+ setFeatureEnabledImpl(Features, "mwaitx", true);
+ LLVM_FALLTHROUGH;
+ case CK_BDVER3:
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ LLVM_FALLTHROUGH;
+ case CK_BDVER2:
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "fma", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "tbm", true);
+ LLVM_FALLTHROUGH;
+ case CK_BDVER1:
+ // xop implies avx, sse4a and fma4.
+ setFeatureEnabledImpl(Features, "xop", true);
+ setFeatureEnabledImpl(Features, "lwp", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ break;
+ }
+ if (!TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec))
+ return false;
+
+ // Can't do this earlier because we need to be able to explicitly enable
+ // or disable these features and the things that they depend upon.
+
+ // Enable popcnt if sse4.2 is enabled and popcnt is not explicitly disabled.
+ auto I = Features.find("sse4.2");
+ if (I != Features.end() && I->getValue() &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "-popcnt") ==
+ FeaturesVec.end())
+ Features["popcnt"] = true;
+
+ // Enable prfchw if 3DNow! is enabled and prfchw is not explicitly disabled.
+ I = Features.find("3dnow");
+ if (I != Features.end() && I->getValue() &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "-prfchw") ==
+ FeaturesVec.end())
+ Features["prfchw"] = true;
+
+ // Additionally, if SSE is enabled and mmx is not explicitly disabled,
+ // then enable MMX.
+ I = Features.find("sse");
+ if (I != Features.end() && I->getValue() &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "-mmx") ==
+ FeaturesVec.end())
+ Features["mmx"] = true;
+
+ return true;
+}
+
+void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features,
+ X86SSEEnum Level, bool Enabled) {
+ if (Enabled) {
+ switch (Level) {
+ case AVX512F:
+ Features["avx512f"] = true;
+ LLVM_FALLTHROUGH;
+ case AVX2:
+ Features["avx2"] = true;
+ LLVM_FALLTHROUGH;
+ case AVX:
+ Features["avx"] = true;
+ Features["xsave"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE42:
+ Features["sse4.2"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE41:
+ Features["sse4.1"] = true;
+ LLVM_FALLTHROUGH;
+ case SSSE3:
+ Features["ssse3"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE3:
+ Features["sse3"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE2:
+ Features["sse2"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE1:
+ Features["sse"] = true;
+ LLVM_FALLTHROUGH;
+ case NoSSE:
+ break;
+ }
+ return;
+ }
+
+ switch (Level) {
+ case NoSSE:
+ case SSE1:
+ Features["sse"] = false;
+ LLVM_FALLTHROUGH;
+ case SSE2:
+ Features["sse2"] = Features["pclmul"] = Features["aes"] = Features["sha"] =
+ false;
+ LLVM_FALLTHROUGH;
+ case SSE3:
+ Features["sse3"] = false;
+ setXOPLevel(Features, NoXOP, false);
+ LLVM_FALLTHROUGH;
+ case SSSE3:
+ Features["ssse3"] = false;
+ LLVM_FALLTHROUGH;
+ case SSE41:
+ Features["sse4.1"] = false;
+ LLVM_FALLTHROUGH;
+ case SSE42:
+ Features["sse4.2"] = false;
+ LLVM_FALLTHROUGH;
+ case AVX:
+ Features["fma"] = Features["avx"] = Features["f16c"] = Features["xsave"] =
+ Features["xsaveopt"] = false;
+ setXOPLevel(Features, FMA4, false);
+ LLVM_FALLTHROUGH;
+ case AVX2:
+ Features["avx2"] = false;
+ LLVM_FALLTHROUGH;
+ case AVX512F:
+ Features["avx512f"] = Features["avx512cd"] = Features["avx512er"] =
+ Features["avx512pf"] = Features["avx512dq"] = Features["avx512bw"] =
+ Features["avx512vl"] = Features["avx512vbmi"] =
+ Features["avx512ifma"] = Features["avx512vpopcntdq"] = false;
+ break;
+ }
+}
+
+void X86TargetInfo::setMMXLevel(llvm::StringMap<bool> &Features,
+ MMX3DNowEnum Level, bool Enabled) {
+ if (Enabled) {
+ switch (Level) {
+ case AMD3DNowAthlon:
+ Features["3dnowa"] = true;
+ LLVM_FALLTHROUGH;
+ case AMD3DNow:
+ Features["3dnow"] = true;
+ LLVM_FALLTHROUGH;
+ case MMX:
+ Features["mmx"] = true;
+ LLVM_FALLTHROUGH;
+ case NoMMX3DNow:
+ break;
+ }
+ return;
+ }
+
+ switch (Level) {
+ case NoMMX3DNow:
+ case MMX:
+ Features["mmx"] = false;
+ LLVM_FALLTHROUGH;
+ case AMD3DNow:
+ Features["3dnow"] = false;
+ LLVM_FALLTHROUGH;
+ case AMD3DNowAthlon:
+ Features["3dnowa"] = false;
+ break;
+ }
+}
+
+void X86TargetInfo::setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level,
+ bool Enabled) {
+ if (Enabled) {
+ switch (Level) {
+ case XOP:
+ Features["xop"] = true;
+ LLVM_FALLTHROUGH;
+ case FMA4:
+ Features["fma4"] = true;
+ setSSELevel(Features, AVX, true);
+ LLVM_FALLTHROUGH;
+ case SSE4A:
+ Features["sse4a"] = true;
+ setSSELevel(Features, SSE3, true);
+ LLVM_FALLTHROUGH;
+ case NoXOP:
+ break;
+ }
+ return;
+ }
+
+ switch (Level) {
+ case NoXOP:
+ case SSE4A:
+ Features["sse4a"] = false;
+ LLVM_FALLTHROUGH;
+ case FMA4:
+ Features["fma4"] = false;
+ LLVM_FALLTHROUGH;
+ case XOP:
+ Features["xop"] = false;
+ break;
+ }
+}
+
+void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
+ StringRef Name, bool Enabled) {
+ // This is a bit of a hack to deal with the sse4 target feature when used
+ // as part of the target attribute. We handle sse4 correctly everywhere
+ // else. See below for more information on how we handle the sse4 options.
+ if (Name != "sse4")
+ Features[Name] = Enabled;
+
+ if (Name == "mmx") {
+ setMMXLevel(Features, MMX, Enabled);
+ } else if (Name == "sse") {
+ setSSELevel(Features, SSE1, Enabled);
+ } else if (Name == "sse2") {
+ setSSELevel(Features, SSE2, Enabled);
+ } else if (Name == "sse3") {
+ setSSELevel(Features, SSE3, Enabled);
+ } else if (Name == "ssse3") {
+ setSSELevel(Features, SSSE3, Enabled);
+ } else if (Name == "sse4.2") {
+ setSSELevel(Features, SSE42, Enabled);
+ } else if (Name == "sse4.1") {
+ setSSELevel(Features, SSE41, Enabled);
+ } else if (Name == "3dnow") {
+ setMMXLevel(Features, AMD3DNow, Enabled);
+ } else if (Name == "3dnowa") {
+ setMMXLevel(Features, AMD3DNowAthlon, Enabled);
+ } else if (Name == "aes") {
+ if (Enabled)
+ setSSELevel(Features, SSE2, Enabled);
+ } else if (Name == "pclmul") {
+ if (Enabled)
+ setSSELevel(Features, SSE2, Enabled);
+ } else if (Name == "avx") {
+ setSSELevel(Features, AVX, Enabled);
+ } else if (Name == "avx2") {
+ setSSELevel(Features, AVX2, Enabled);
+ } else if (Name == "avx512f") {
+ setSSELevel(Features, AVX512F, Enabled);
+ } else if (Name == "avx512cd" || Name == "avx512er" || Name == "avx512pf" ||
+ Name == "avx512dq" || Name == "avx512bw" || Name == "avx512vl" ||
+ Name == "avx512vbmi" || Name == "avx512ifma" ||
+ Name == "avx512vpopcntdq") {
+ if (Enabled)
+ setSSELevel(Features, AVX512F, Enabled);
+ // Enable BWI instruction if VBMI is being enabled.
+ if (Name == "avx512vbmi" && Enabled)
+ Features["avx512bw"] = true;
+ // Also disable VBMI if BWI is being disabled.
+ if (Name == "avx512bw" && !Enabled)
+ Features["avx512vbmi"] = false;
+ } else if (Name == "fma") {
+ if (Enabled)
+ setSSELevel(Features, AVX, Enabled);
+ } else if (Name == "fma4") {
+ setXOPLevel(Features, FMA4, Enabled);
+ } else if (Name == "xop") {
+ setXOPLevel(Features, XOP, Enabled);
+ } else if (Name == "sse4a") {
+ setXOPLevel(Features, SSE4A, Enabled);
+ } else if (Name == "f16c") {
+ if (Enabled)
+ setSSELevel(Features, AVX, Enabled);
+ } else if (Name == "sha") {
+ if (Enabled)
+ setSSELevel(Features, SSE2, Enabled);
+ } else if (Name == "sse4") {
+ // We can get here via the __target__ attribute since that's not controlled
+ // via the -msse4/-mno-sse4 command line alias. Handle this the same way
+ // here - turn on the sse4.2 if enabled, turn off the sse4.1 level if
+ // disabled.
+ if (Enabled)
+ setSSELevel(Features, SSE42, Enabled);
+ else
+ setSSELevel(Features, SSE41, Enabled);
+ } else if (Name == "xsave") {
+ if (!Enabled)
+ Features["xsaveopt"] = false;
+ } else if (Name == "xsaveopt" || Name == "xsavec" || Name == "xsaves") {
+ if (Enabled)
+ Features["xsave"] = true;
+ }
+}
+
+/// handleTargetFeatures - Perform initialization based on the user
+/// configured set of features.
+bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ for (const auto &Feature : Features) {
+ if (Feature[0] != '+')
+ continue;
+
+ if (Feature == "+aes") {
+ HasAES = true;
+ } else if (Feature == "+pclmul") {
+ HasPCLMUL = true;
+ } else if (Feature == "+lzcnt") {
+ HasLZCNT = true;
+ } else if (Feature == "+rdrnd") {
+ HasRDRND = true;
+ } else if (Feature == "+fsgsbase") {
+ HasFSGSBASE = true;
+ } else if (Feature == "+bmi") {
+ HasBMI = true;
+ } else if (Feature == "+bmi2") {
+ HasBMI2 = true;
+ } else if (Feature == "+popcnt") {
+ HasPOPCNT = true;
+ } else if (Feature == "+rtm") {
+ HasRTM = true;
+ } else if (Feature == "+prfchw") {
+ HasPRFCHW = true;
+ } else if (Feature == "+rdseed") {
+ HasRDSEED = true;
+ } else if (Feature == "+adx") {
+ HasADX = true;
+ } else if (Feature == "+tbm") {
+ HasTBM = true;
+ } else if (Feature == "+lwp") {
+ HasLWP = true;
+ } else if (Feature == "+fma") {
+ HasFMA = true;
+ } else if (Feature == "+f16c") {
+ HasF16C = true;
+ } else if (Feature == "+avx512cd") {
+ HasAVX512CD = true;
+ } else if (Feature == "+avx512vpopcntdq") {
+ HasAVX512VPOPCNTDQ = true;
+ } else if (Feature == "+avx512er") {
+ HasAVX512ER = true;
+ } else if (Feature == "+avx512pf") {
+ HasAVX512PF = true;
+ } else if (Feature == "+avx512dq") {
+ HasAVX512DQ = true;
+ } else if (Feature == "+avx512bw") {
+ HasAVX512BW = true;
+ } else if (Feature == "+avx512vl") {
+ HasAVX512VL = true;
+ } else if (Feature == "+avx512vbmi") {
+ HasAVX512VBMI = true;
+ } else if (Feature == "+avx512ifma") {
+ HasAVX512IFMA = true;
+ } else if (Feature == "+sha") {
+ HasSHA = true;
+ } else if (Feature == "+mpx") {
+ HasMPX = true;
+ } else if (Feature == "+shstk") {
+ HasSHSTK = true;
+ } else if (Feature == "+ibt") {
+ HasIBT = true;
+ } else if (Feature == "+movbe") {
+ HasMOVBE = true;
+ } else if (Feature == "+sgx") {
+ HasSGX = true;
+ } else if (Feature == "+cx16") {
+ HasCX16 = true;
+ } else if (Feature == "+fxsr") {
+ HasFXSR = true;
+ } else if (Feature == "+xsave") {
+ HasXSAVE = true;
+ } else if (Feature == "+xsaveopt") {
+ HasXSAVEOPT = true;
+ } else if (Feature == "+xsavec") {
+ HasXSAVEC = true;
+ } else if (Feature == "+xsaves") {
+ HasXSAVES = true;
+ } else if (Feature == "+mwaitx") {
+ HasMWAITX = true;
+ } else if (Feature == "+pku") {
+ HasPKU = true;
+ } else if (Feature == "+clflushopt") {
+ HasCLFLUSHOPT = true;
+ } else if (Feature == "+clwb") {
+ HasCLWB = true;
+ } else if (Feature == "+prefetchwt1") {
+ HasPREFETCHWT1 = true;
+ } else if (Feature == "+clzero") {
+ HasCLZERO = true;
+ }
+
+ X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Feature)
+ .Case("+avx512f", AVX512F)
+ .Case("+avx2", AVX2)
+ .Case("+avx", AVX)
+ .Case("+sse4.2", SSE42)
+ .Case("+sse4.1", SSE41)
+ .Case("+ssse3", SSSE3)
+ .Case("+sse3", SSE3)
+ .Case("+sse2", SSE2)
+ .Case("+sse", SSE1)
+ .Default(NoSSE);
+ SSELevel = std::max(SSELevel, Level);
+
+ MMX3DNowEnum ThreeDNowLevel = llvm::StringSwitch<MMX3DNowEnum>(Feature)
+ .Case("+3dnowa", AMD3DNowAthlon)
+ .Case("+3dnow", AMD3DNow)
+ .Case("+mmx", MMX)
+ .Default(NoMMX3DNow);
+ MMX3DNowLevel = std::max(MMX3DNowLevel, ThreeDNowLevel);
+
+ XOPEnum XLevel = llvm::StringSwitch<XOPEnum>(Feature)
+ .Case("+xop", XOP)
+ .Case("+fma4", FMA4)
+ .Case("+sse4a", SSE4A)
+ .Default(NoXOP);
+ XOPLevel = std::max(XOPLevel, XLevel);
+ }
+
+ // LLVM doesn't have a separate switch for fpmath, so only accept it if it
+ // matches the selected sse level.
+ if ((FPMath == FP_SSE && SSELevel < SSE1) ||
+ (FPMath == FP_387 && SSELevel >= SSE1)) {
+ Diags.Report(diag::err_target_unsupported_fpmath)
+ << (FPMath == FP_SSE ? "sse" : "387");
+ return false;
+ }
+
+ SimdDefaultAlign =
+ hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
+ return true;
+}
+
+/// X86TargetInfo::getTargetDefines - Return the set of the X86-specific macro
+/// definitions for this particular subtarget.
+void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Target identification.
+ if (getTriple().getArch() == llvm::Triple::x86_64) {
+ Builder.defineMacro("__amd64__");
+ Builder.defineMacro("__amd64");
+ Builder.defineMacro("__x86_64");
+ Builder.defineMacro("__x86_64__");
+ if (getTriple().getArchName() == "x86_64h") {
+ Builder.defineMacro("__x86_64h");
+ Builder.defineMacro("__x86_64h__");
+ }
+ } else {
+ DefineStd(Builder, "i386", Opts);
+ }
+
+ // Subtarget options.
+ // FIXME: We are hard-coding the tune parameters based on the CPU, but they
+ // truly should be based on -mtune options.
+ switch (CPU) {
+ case CK_Generic:
+ break;
+ case CK_i386:
+ // The rest are coming from the i386 define above.
+ Builder.defineMacro("__tune_i386__");
+ break;
+ case CK_i486:
+ case CK_WinChipC6:
+ case CK_WinChip2:
+ case CK_C3:
+ defineCPUMacros(Builder, "i486");
+ break;
+ case CK_PentiumMMX:
+ Builder.defineMacro("__pentium_mmx__");
+ Builder.defineMacro("__tune_pentium_mmx__");
+ LLVM_FALLTHROUGH;
+ case CK_i586:
+ case CK_Pentium:
+ defineCPUMacros(Builder, "i586");
+ defineCPUMacros(Builder, "pentium");
+ break;
+ case CK_Pentium3:
+ case CK_PentiumM:
+ Builder.defineMacro("__tune_pentium3__");
+ LLVM_FALLTHROUGH;
+ case CK_Pentium2:
+ case CK_C3_2:
+ Builder.defineMacro("__tune_pentium2__");
+ LLVM_FALLTHROUGH;
+ case CK_PentiumPro:
+ defineCPUMacros(Builder, "i686");
+ defineCPUMacros(Builder, "pentiumpro");
+ break;
+ case CK_Pentium4:
+ defineCPUMacros(Builder, "pentium4");
+ break;
+ case CK_Yonah:
+ case CK_Prescott:
+ case CK_Nocona:
+ defineCPUMacros(Builder, "nocona");
+ break;
+ case CK_Core2:
+ case CK_Penryn:
+ defineCPUMacros(Builder, "core2");
+ break;
+ case CK_Bonnell:
+ defineCPUMacros(Builder, "atom");
+ break;
+ case CK_Silvermont:
+ defineCPUMacros(Builder, "slm");
+ break;
+ case CK_Goldmont:
+ defineCPUMacros(Builder, "goldmont");
+ break;
+ case CK_Nehalem:
+ case CK_Westmere:
+ case CK_SandyBridge:
+ case CK_IvyBridge:
+ case CK_Haswell:
+ case CK_Broadwell:
+ case CK_SkylakeClient:
+ case CK_SkylakeServer:
+ case CK_Cannonlake:
+ case CK_Icelake:
+ // FIXME: Historically, we defined this legacy name, it would be nice to
+ // remove it at some point. We've never exposed fine-grained names for
+ // recent primary x86 CPUs, and we should keep it that way.
+ defineCPUMacros(Builder, "corei7");
+ break;
+ case CK_KNL:
+ defineCPUMacros(Builder, "knl");
+ break;
+ case CK_KNM:
+ break;
+ case CK_Lakemont:
+ defineCPUMacros(Builder, "i586", /*Tuning*/false);
+ defineCPUMacros(Builder, "pentium", /*Tuning*/false);
+ Builder.defineMacro("__tune_lakemont__");
+ break;
+ case CK_K6_2:
+ Builder.defineMacro("__k6_2__");
+ Builder.defineMacro("__tune_k6_2__");
+ LLVM_FALLTHROUGH;
+ case CK_K6_3:
+ if (CPU != CK_K6_2) { // In case of fallthrough
+ // FIXME: GCC may be enabling these in cases where some other k6
+ // architecture is specified but -m3dnow is explicitly provided. The
+ // exact semantics need to be determined and emulated here.
+ Builder.defineMacro("__k6_3__");
+ Builder.defineMacro("__tune_k6_3__");
+ }
+ LLVM_FALLTHROUGH;
+ case CK_K6:
+ defineCPUMacros(Builder, "k6");
+ break;
+ case CK_Athlon:
+ case CK_AthlonXP:
+ defineCPUMacros(Builder, "athlon");
+ if (SSELevel != NoSSE) {
+ Builder.defineMacro("__athlon_sse__");
+ Builder.defineMacro("__tune_athlon_sse__");
+ }
+ break;
+ case CK_K8:
+ case CK_K8SSE3:
+ case CK_x86_64:
+ defineCPUMacros(Builder, "k8");
+ break;
+ case CK_AMDFAM10:
+ defineCPUMacros(Builder, "amdfam10");
+ break;
+ case CK_BTVER1:
+ defineCPUMacros(Builder, "btver1");
+ break;
+ case CK_BTVER2:
+ defineCPUMacros(Builder, "btver2");
+ break;
+ case CK_BDVER1:
+ defineCPUMacros(Builder, "bdver1");
+ break;
+ case CK_BDVER2:
+ defineCPUMacros(Builder, "bdver2");
+ break;
+ case CK_BDVER3:
+ defineCPUMacros(Builder, "bdver3");
+ break;
+ case CK_BDVER4:
+ defineCPUMacros(Builder, "bdver4");
+ break;
+ case CK_ZNVER1:
+ defineCPUMacros(Builder, "znver1");
+ break;
+ case CK_Geode:
+ defineCPUMacros(Builder, "geode");
+ break;
+ }
+
+ // Target properties.
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ // Define __NO_MATH_INLINES on linux/x86 so that we don't get inline
+ // functions in glibc header files that use FP Stack inline asm which the
+ // backend can't deal with (PR879).
+ Builder.defineMacro("__NO_MATH_INLINES");
+
+ if (HasAES)
+ Builder.defineMacro("__AES__");
+
+ if (HasPCLMUL)
+ Builder.defineMacro("__PCLMUL__");
+
+ if (HasLZCNT)
+ Builder.defineMacro("__LZCNT__");
+
+ if (HasRDRND)
+ Builder.defineMacro("__RDRND__");
+
+ if (HasFSGSBASE)
+ Builder.defineMacro("__FSGSBASE__");
+
+ if (HasBMI)
+ Builder.defineMacro("__BMI__");
+
+ if (HasBMI2)
+ Builder.defineMacro("__BMI2__");
+
+ if (HasPOPCNT)
+ Builder.defineMacro("__POPCNT__");
+
+ if (HasRTM)
+ Builder.defineMacro("__RTM__");
+
+ if (HasPRFCHW)
+ Builder.defineMacro("__PRFCHW__");
+
+ if (HasRDSEED)
+ Builder.defineMacro("__RDSEED__");
+
+ if (HasADX)
+ Builder.defineMacro("__ADX__");
+
+ if (HasTBM)
+ Builder.defineMacro("__TBM__");
+
+ if (HasLWP)
+ Builder.defineMacro("__LWP__");
+
+ if (HasMWAITX)
+ Builder.defineMacro("__MWAITX__");
+
+ switch (XOPLevel) {
+ case XOP:
+ Builder.defineMacro("__XOP__");
+ LLVM_FALLTHROUGH;
+ case FMA4:
+ Builder.defineMacro("__FMA4__");
+ LLVM_FALLTHROUGH;
+ case SSE4A:
+ Builder.defineMacro("__SSE4A__");
+ LLVM_FALLTHROUGH;
+ case NoXOP:
+ break;
+ }
+
+ if (HasFMA)
+ Builder.defineMacro("__FMA__");
+
+ if (HasF16C)
+ Builder.defineMacro("__F16C__");
+
+ if (HasAVX512CD)
+ Builder.defineMacro("__AVX512CD__");
+ if (HasAVX512VPOPCNTDQ)
+ Builder.defineMacro("__AVX512VPOPCNTDQ__");
+ if (HasAVX512ER)
+ Builder.defineMacro("__AVX512ER__");
+ if (HasAVX512PF)
+ Builder.defineMacro("__AVX512PF__");
+ if (HasAVX512DQ)
+ Builder.defineMacro("__AVX512DQ__");
+ if (HasAVX512BW)
+ Builder.defineMacro("__AVX512BW__");
+ if (HasAVX512VL)
+ Builder.defineMacro("__AVX512VL__");
+ if (HasAVX512VBMI)
+ Builder.defineMacro("__AVX512VBMI__");
+ if (HasAVX512IFMA)
+ Builder.defineMacro("__AVX512IFMA__");
+
+ if (HasSHA)
+ Builder.defineMacro("__SHA__");
+
+ if (HasFXSR)
+ Builder.defineMacro("__FXSR__");
+ if (HasXSAVE)
+ Builder.defineMacro("__XSAVE__");
+ if (HasXSAVEOPT)
+ Builder.defineMacro("__XSAVEOPT__");
+ if (HasXSAVEC)
+ Builder.defineMacro("__XSAVEC__");
+ if (HasXSAVES)
+ Builder.defineMacro("__XSAVES__");
+ if (HasPKU)
+ Builder.defineMacro("__PKU__");
+ if (HasCX16)
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
+ if (HasCLFLUSHOPT)
+ Builder.defineMacro("__CLFLUSHOPT__");
+ if (HasCLWB)
+ Builder.defineMacro("__CLWB__");
+ if (HasMPX)
+ Builder.defineMacro("__MPX__");
+ if (HasSHSTK)
+ Builder.defineMacro("__SHSTK__");
+ if (HasSGX)
+ Builder.defineMacro("__SGX__");
+ if (HasPREFETCHWT1)
+ Builder.defineMacro("__PREFETCHWT1__");
+ if (HasCLZERO)
+ Builder.defineMacro("__CLZERO__");
+
+ // Each case falls through to the previous one here.
+ switch (SSELevel) {
+ case AVX512F:
+ Builder.defineMacro("__AVX512F__");
+ LLVM_FALLTHROUGH;
+ case AVX2:
+ Builder.defineMacro("__AVX2__");
+ LLVM_FALLTHROUGH;
+ case AVX:
+ Builder.defineMacro("__AVX__");
+ LLVM_FALLTHROUGH;
+ case SSE42:
+ Builder.defineMacro("__SSE4_2__");
+ LLVM_FALLTHROUGH;
+ case SSE41:
+ Builder.defineMacro("__SSE4_1__");
+ LLVM_FALLTHROUGH;
+ case SSSE3:
+ Builder.defineMacro("__SSSE3__");
+ LLVM_FALLTHROUGH;
+ case SSE3:
+ Builder.defineMacro("__SSE3__");
+ LLVM_FALLTHROUGH;
+ case SSE2:
+ Builder.defineMacro("__SSE2__");
+ Builder.defineMacro("__SSE2_MATH__"); // -mfp-math=sse always implied.
+ LLVM_FALLTHROUGH;
+ case SSE1:
+ Builder.defineMacro("__SSE__");
+ Builder.defineMacro("__SSE_MATH__"); // -mfp-math=sse always implied.
+ LLVM_FALLTHROUGH;
+ case NoSSE:
+ break;
+ }
+
+ if (Opts.MicrosoftExt && getTriple().getArch() == llvm::Triple::x86) {
+ switch (SSELevel) {
+ case AVX512F:
+ case AVX2:
+ case AVX:
+ case SSE42:
+ case SSE41:
+ case SSSE3:
+ case SSE3:
+ case SSE2:
+ Builder.defineMacro("_M_IX86_FP", Twine(2));
+ break;
+ case SSE1:
+ Builder.defineMacro("_M_IX86_FP", Twine(1));
+ break;
+ default:
+ Builder.defineMacro("_M_IX86_FP", Twine(0));
+ break;
+ }
+ }
+
+ // Each case falls through to the previous one here.
+ switch (MMX3DNowLevel) {
+ case AMD3DNowAthlon:
+ Builder.defineMacro("__3dNOW_A__");
+ LLVM_FALLTHROUGH;
+ case AMD3DNow:
+ Builder.defineMacro("__3dNOW__");
+ LLVM_FALLTHROUGH;
+ case MMX:
+ Builder.defineMacro("__MMX__");
+ LLVM_FALLTHROUGH;
+ case NoMMX3DNow:
+ break;
+ }
+
+ if (CPU >= CK_i486) {
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ }
+ if (CPU >= CK_i586)
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+
+ if (HasFloat128)
+ Builder.defineMacro("__SIZEOF_FLOAT128__", "16");
+}
+
+bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
+ return llvm::StringSwitch<bool>(Name)
+ .Case("3dnow", true)
+ .Case("3dnowa", true)
+ .Case("aes", true)
+ .Case("avx", true)
+ .Case("avx2", true)
+ .Case("avx512f", true)
+ .Case("avx512cd", true)
+ .Case("avx512vpopcntdq", true)
+ .Case("avx512er", true)
+ .Case("avx512pf", true)
+ .Case("avx512dq", true)
+ .Case("avx512bw", true)
+ .Case("avx512vl", true)
+ .Case("avx512vbmi", true)
+ .Case("avx512ifma", true)
+ .Case("bmi", true)
+ .Case("bmi2", true)
+ .Case("clflushopt", true)
+ .Case("clwb", true)
+ .Case("clzero", true)
+ .Case("cx16", true)
+ .Case("f16c", true)
+ .Case("fma", true)
+ .Case("fma4", true)
+ .Case("fsgsbase", true)
+ .Case("fxsr", true)
+ .Case("lwp", true)
+ .Case("lzcnt", true)
+ .Case("mmx", true)
+ .Case("movbe", true)
+ .Case("mpx", true)
+ .Case("pclmul", true)
+ .Case("pku", true)
+ .Case("popcnt", true)
+ .Case("prefetchwt1", true)
+ .Case("prfchw", true)
+ .Case("rdrnd", true)
+ .Case("rdseed", true)
+ .Case("rtm", true)
+ .Case("sgx", true)
+ .Case("sha", true)
+ .Case("sse", true)
+ .Case("sse2", true)
+ .Case("sse3", true)
+ .Case("ssse3", true)
+ .Case("sse4", true)
+ .Case("sse4.1", true)
+ .Case("sse4.2", true)
+ .Case("sse4a", true)
+ .Case("tbm", true)
+ .Case("x87", true)
+ .Case("xop", true)
+ .Case("xsave", true)
+ .Case("xsavec", true)
+ .Case("xsaves", true)
+ .Case("xsaveopt", true)
+ .Default(false);
+}
+
+bool X86TargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("aes", HasAES)
+ .Case("avx", SSELevel >= AVX)
+ .Case("avx2", SSELevel >= AVX2)
+ .Case("avx512f", SSELevel >= AVX512F)
+ .Case("avx512cd", HasAVX512CD)
+ .Case("avx512vpopcntdq", HasAVX512VPOPCNTDQ)
+ .Case("avx512er", HasAVX512ER)
+ .Case("avx512pf", HasAVX512PF)
+ .Case("avx512dq", HasAVX512DQ)
+ .Case("avx512bw", HasAVX512BW)
+ .Case("avx512vl", HasAVX512VL)
+ .Case("avx512vbmi", HasAVX512VBMI)
+ .Case("avx512ifma", HasAVX512IFMA)
+ .Case("bmi", HasBMI)
+ .Case("bmi2", HasBMI2)
+ .Case("clflushopt", HasCLFLUSHOPT)
+ .Case("clwb", HasCLWB)
+ .Case("clzero", HasCLZERO)
+ .Case("cx16", HasCX16)
+ .Case("f16c", HasF16C)
+ .Case("fma", HasFMA)
+ .Case("fma4", XOPLevel >= FMA4)
+ .Case("fsgsbase", HasFSGSBASE)
+ .Case("fxsr", HasFXSR)
+ .Case("lwp", HasLWP)
+ .Case("lzcnt", HasLZCNT)
+ .Case("mm3dnow", MMX3DNowLevel >= AMD3DNow)
+ .Case("mm3dnowa", MMX3DNowLevel >= AMD3DNowAthlon)
+ .Case("mmx", MMX3DNowLevel >= MMX)
+ .Case("movbe", HasMOVBE)
+ .Case("mpx", HasMPX)
+ .Case("shstk", HasSHSTK)
+ .Case("ibt", HasIBT)
+ .Case("pclmul", HasPCLMUL)
+ .Case("pku", HasPKU)
+ .Case("popcnt", HasPOPCNT)
+ .Case("prefetchwt1", HasPREFETCHWT1)
+ .Case("prfchw", HasPRFCHW)
+ .Case("rdrnd", HasRDRND)
+ .Case("rdseed", HasRDSEED)
+ .Case("rtm", HasRTM)
+ .Case("sgx", HasSGX)
+ .Case("sha", HasSHA)
+ .Case("sse", SSELevel >= SSE1)
+ .Case("sse2", SSELevel >= SSE2)
+ .Case("sse3", SSELevel >= SSE3)
+ .Case("ssse3", SSELevel >= SSSE3)
+ .Case("sse4.1", SSELevel >= SSE41)
+ .Case("sse4.2", SSELevel >= SSE42)
+ .Case("sse4a", XOPLevel >= SSE4A)
+ .Case("tbm", HasTBM)
+ .Case("x86", true)
+ .Case("x86_32", getTriple().getArch() == llvm::Triple::x86)
+ .Case("x86_64", getTriple().getArch() == llvm::Triple::x86_64)
+ .Case("xop", XOPLevel >= XOP)
+ .Case("xsave", HasXSAVE)
+ .Case("xsavec", HasXSAVEC)
+ .Case("xsaves", HasXSAVES)
+ .Case("xsaveopt", HasXSAVEOPT)
+ .Default(false);
+}
+
+// We can't use a generic validation scheme for the features accepted here
+// versus subtarget features accepted in the target attribute because the
+// bitfield structure that's initialized in the runtime only supports the
+// below currently rather than the full range of subtarget features. (See
+// X86TargetInfo::hasFeature for a somewhat comprehensive list).
+bool X86TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
+ return llvm::StringSwitch<bool>(FeatureStr)
+#define X86_FEATURE_COMPAT(VAL, ENUM, STR) .Case(STR, true)
+#include "llvm/Support/X86TargetParser.def"
+ .Default(false);
+}
+
+// We can't use a generic validation scheme for the cpus accepted here
+// versus subtarget cpus accepted in the target attribute because the
+// variables intitialized by the runtime only support the below currently
+// rather than the full range of cpus.
+bool X86TargetInfo::validateCpuIs(StringRef FeatureStr) const {
+ return llvm::StringSwitch<bool>(FeatureStr)
+#define X86_VENDOR(ENUM, STRING) .Case(STRING, true)
+#define X86_CPU_TYPE_COMPAT_WITH_ALIAS(ARCHNAME, ENUM, STR, ALIAS) \
+ .Cases(STR, ALIAS, true)
+#define X86_CPU_TYPE_COMPAT(ARCHNAME, ENUM, STR) .Case(STR, true)
+#define X86_CPU_SUBTYPE_COMPAT(ARCHNAME, ENUM, STR) .Case(STR, true)
+#include "llvm/Support/X86TargetParser.def"
+ .Default(false);
+}
+
+bool X86TargetInfo::validateAsmConstraint(
+ const char *&Name, TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default:
+ return false;
+ // Constant constraints.
+ case 'e': // 32-bit signed integer constant for use with sign-extending x86_64
+ // instructions.
+ case 'Z': // 32-bit unsigned integer constant for use with zero-extending
+ // x86_64 instructions.
+ case 's':
+ Info.setRequiresImmediate();
+ return true;
+ case 'I':
+ Info.setRequiresImmediate(0, 31);
+ return true;
+ case 'J':
+ Info.setRequiresImmediate(0, 63);
+ return true;
+ case 'K':
+ Info.setRequiresImmediate(-128, 127);
+ return true;
+ case 'L':
+ Info.setRequiresImmediate({int(0xff), int(0xffff), int(0xffffffff)});
+ return true;
+ case 'M':
+ Info.setRequiresImmediate(0, 3);
+ return true;
+ case 'N':
+ Info.setRequiresImmediate(0, 255);
+ return true;
+ case 'O':
+ Info.setRequiresImmediate(0, 127);
+ return true;
+ // Register constraints.
+ case 'Y': // 'Y' is the first character for several 2-character constraints.
+ // Shift the pointer to the second character of the constraint.
+ Name++;
+ switch (*Name) {
+ default:
+ return false;
+ case 'z':
+ case '0': // First SSE register.
+ case '2':
+ case 't': // Any SSE register, when SSE2 is enabled.
+ case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled.
+ case 'm': // Any MMX register, when inter-unit moves enabled.
+ case 'k': // AVX512 arch mask registers: k1-k7.
+ Info.setAllowsRegister();
+ return true;
+ }
+ case 'f': // Any x87 floating point stack register.
+ // Constraint 'f' cannot be used for output operands.
+ if (Info.ConstraintStr[0] == '=')
+ return false;
+ Info.setAllowsRegister();
+ return true;
+ case 'a': // eax.
+ case 'b': // ebx.
+ case 'c': // ecx.
+ case 'd': // edx.
+ case 'S': // esi.
+ case 'D': // edi.
+ case 'A': // edx:eax.
+ case 't': // Top of floating point stack.
+ case 'u': // Second from top of floating point stack.
+ case 'q': // Any register accessible as [r]l: a, b, c, and d.
+ case 'y': // Any MMX register.
+ case 'v': // Any {X,Y,Z}MM register (Arch & context dependent)
+ case 'x': // Any SSE register.
+ case 'k': // Any AVX512 mask register (same as Yk, additionaly allows k0
+ // for intermideate k reg operations).
+ case 'Q': // Any register accessible as [r]h: a, b, c, and d.
+ case 'R': // "Legacy" registers: ax, bx, cx, dx, di, si, sp, bp.
+ case 'l': // "Index" registers: any general register that can be used as an
+ // index in a base+index memory access.
+ Info.setAllowsRegister();
+ return true;
+ // Floating point constant constraints.
+ case 'C': // SSE floating point constant.
+ case 'G': // x87 floating point constant.
+ return true;
+ }
+}
+
+bool X86TargetInfo::validateOutputSize(StringRef Constraint,
+ unsigned Size) const {
+ // Strip off constraint modifiers.
+ while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
+ Constraint = Constraint.substr(1);
+
+ return validateOperandSize(Constraint, Size);
+}
+
+bool X86TargetInfo::validateInputSize(StringRef Constraint,
+ unsigned Size) const {
+ return validateOperandSize(Constraint, Size);
+}
+
+bool X86TargetInfo::validateOperandSize(StringRef Constraint,
+ unsigned Size) const {
+ switch (Constraint[0]) {
+ default:
+ break;
+ case 'k':
+ // Registers k0-k7 (AVX512) size limit is 64 bit.
+ case 'y':
+ return Size <= 64;
+ case 'f':
+ case 't':
+ case 'u':
+ return Size <= 128;
+ case 'Y':
+ // 'Y' is the first character for several 2-character constraints.
+ switch (Constraint[1]) {
+ default:
+ return false;
+ case 'm':
+ // 'Ym' is synonymous with 'y'.
+ case 'k':
+ return Size <= 64;
+ case 'z':
+ case '0':
+ // XMM0
+ if (SSELevel >= SSE1)
+ return Size <= 128U;
+ return false;
+ case 'i':
+ case 't':
+ case '2':
+ // 'Yi','Yt','Y2' are synonymous with 'x' when SSE2 is enabled.
+ if (SSELevel < SSE2)
+ return false;
+ break;
+ }
+ case 'v':
+ case 'x':
+ if (SSELevel >= AVX512F)
+ // 512-bit zmm registers can be used if target supports AVX512F.
+ return Size <= 512U;
+ else if (SSELevel >= AVX)
+ // 256-bit ymm registers can be used if target supports AVX.
+ return Size <= 256U;
+ return Size <= 128U;
+
+ }
+
+ return true;
+}
+
+std::string X86TargetInfo::convertConstraint(const char *&Constraint) const {
+ switch (*Constraint) {
+ case 'a':
+ return std::string("{ax}");
+ case 'b':
+ return std::string("{bx}");
+ case 'c':
+ return std::string("{cx}");
+ case 'd':
+ return std::string("{dx}");
+ case 'S':
+ return std::string("{si}");
+ case 'D':
+ return std::string("{di}");
+ case 'p': // address
+ return std::string("im");
+ case 't': // top of floating point stack.
+ return std::string("{st}");
+ case 'u': // second from top of floating point stack.
+ return std::string("{st(1)}"); // second from top of floating point stack.
+ case 'Y':
+ switch (Constraint[1]) {
+ default:
+ // Break from inner switch and fall through (copy single char),
+ // continue parsing after copying the current constraint into
+ // the return string.
+ break;
+ case 'k':
+ case 'm':
+ case 'i':
+ case 't':
+ case 'z':
+ case '0':
+ case '2':
+ // "^" hints llvm that this is a 2 letter constraint.
+ // "Constraint++" is used to promote the string iterator
+ // to the next constraint.
+ return std::string("^") + std::string(Constraint++, 2);
+ }
+ LLVM_FALLTHROUGH;
+ default:
+ return std::string(1, *Constraint);
+ }
+}
+
+bool X86TargetInfo::checkCPUKind(CPUKind Kind) const {
+ // Perform any per-CPU checks necessary to determine if this CPU is
+ // acceptable.
+ // FIXME: This results in terrible diagnostics. Clang just says the CPU is
+ // invalid without explaining *why*.
+ switch (Kind) {
+ case CK_Generic:
+ // No processor selected!
+ return false;
+#define PROC(ENUM, STRING, IS64BIT) \
+ case CK_##ENUM: \
+ return IS64BIT || getTriple().getArch() == llvm::Triple::x86;
+#include "clang/Basic/X86Target.def"
+ }
+ llvm_unreachable("Unhandled CPU kind");
+}
+
+X86TargetInfo::CPUKind X86TargetInfo::getCPUKind(StringRef CPU) const {
+ return llvm::StringSwitch<CPUKind>(CPU)
+#define PROC(ENUM, STRING, IS64BIT) .Case(STRING, CK_##ENUM)
+#define PROC_ALIAS(ENUM, ALIAS) .Case(ALIAS, CK_##ENUM)
+#include "clang/Basic/X86Target.def"
+ .Default(CK_Generic);
+}
+
+ArrayRef<const char *> X86TargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+ArrayRef<TargetInfo::AddlRegName> X86TargetInfo::getGCCAddlRegNames() const {
+ return llvm::makeArrayRef(AddlRegNames);
+}
+
+ArrayRef<Builtin::Info> X86_32TargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfoX86, clang::X86::LastX86CommonBuiltin -
+ Builtin::FirstTSBuiltin + 1);
+}
+
+ArrayRef<Builtin::Info> X86_64TargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfoX86,
+ X86::LastTSBuiltin - Builtin::FirstTSBuiltin);
+}