2017-07-22 06:37:03 +08:00
|
|
|
//===--- X86.cpp - Implement X86 target feature support -------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2017-07-22 06:37:03 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements X86 TargetInfo objects.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "X86.h"
|
|
|
|
#include "clang/Basic/Builtins.h"
|
|
|
|
#include "clang/Basic/Diagnostic.h"
|
|
|
|
#include "clang/Basic/TargetBuiltins.h"
|
2018-02-09 07:15:02 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2017-07-22 06:37:03 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2020-06-11 12:25:15 +08:00
|
|
|
#include "llvm/Support/X86TargetParser.h"
|
2017-07-22 06:37:03 +08:00
|
|
|
|
|
|
|
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",
|
2017-07-30 18:19:10 +08:00
|
|
|
"cr0", "cr2", "cr3", "cr4", "cr8",
|
2017-08-01 18:51:09 +08:00
|
|
|
"dr0", "dr1", "dr2", "dr3", "dr6", "dr7",
|
2017-11-21 16:50:10 +08:00
|
|
|
"bnd0", "bnd1", "bnd2", "bnd3",
|
2020-07-07 09:50:17 +08:00
|
|
|
"tmm0", "tmm1", "tmm2", "tmm3", "tmm4", "tmm5", "tmm6", "tmm7",
|
2017-07-22 06:37:03 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
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)
|
2020-07-07 14:50:41 +08:00
|
|
|
setFeatureEnabled(Features, "sse2", true);
|
2017-07-22 06:37:03 +08:00
|
|
|
|
2020-06-10 03:18:08 +08:00
|
|
|
using namespace llvm::X86;
|
2017-07-22 06:37:03 +08:00
|
|
|
|
2020-07-01 02:59:03 +08:00
|
|
|
SmallVector<StringRef, 16> CPUFeatures;
|
|
|
|
getFeaturesForCPU(CPU, CPUFeatures);
|
|
|
|
for (auto &F : CPUFeatures)
|
2020-07-07 14:50:41 +08:00
|
|
|
setFeatureEnabled(Features, F, true);
|
2017-07-22 06:37:03 +08:00
|
|
|
|
|
|
|
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() &&
|
2019-03-31 16:48:19 +08:00
|
|
|
llvm::find(FeaturesVec, "-popcnt") == FeaturesVec.end())
|
2017-07-22 06:37:03 +08:00
|
|
|
Features["popcnt"] = 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() &&
|
2019-03-31 16:48:19 +08:00
|
|
|
llvm::find(FeaturesVec, "-mmx") == FeaturesVec.end())
|
2017-07-22 06:37:03 +08:00
|
|
|
Features["mmx"] = true;
|
|
|
|
|
2020-06-27 07:41:30 +08:00
|
|
|
// Enable xsave if avx is enabled and xsave is not explicitly disabled.
|
|
|
|
I = Features.find("avx");
|
|
|
|
if (I != Features.end() && I->getValue() &&
|
|
|
|
llvm::find(FeaturesVec, "-xsave") == FeaturesVec.end())
|
|
|
|
Features["xsave"] = true;
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-07-07 14:50:41 +08:00
|
|
|
void X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
|
|
|
|
StringRef Name, bool Enabled) const {
|
2020-07-07 05:58:31 +08:00
|
|
|
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)
|
|
|
|
Name = "sse4.2";
|
|
|
|
else
|
|
|
|
Name = "sse4.1";
|
|
|
|
}
|
|
|
|
|
|
|
|
Features[Name] = Enabled;
|
2020-08-06 15:13:40 +08:00
|
|
|
llvm::X86::updateImpliedFeatures(Name, Enabled, Features);
|
2017-07-22 06:37:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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;
|
2017-12-27 16:16:54 +08:00
|
|
|
} else if (Feature == "+vaes") {
|
|
|
|
HasVAES = true;
|
2017-07-22 06:37:03 +08:00
|
|
|
} else if (Feature == "+pclmul") {
|
|
|
|
HasPCLMUL = true;
|
2017-12-27 17:00:31 +08:00
|
|
|
} else if (Feature == "+vpclmulqdq") {
|
|
|
|
HasVPCLMULQDQ = true;
|
2017-07-22 06:37:03 +08:00
|
|
|
} 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;
|
2017-12-27 16:37:47 +08:00
|
|
|
} else if (Feature == "+gfni") {
|
|
|
|
HasGFNI = true;
|
2017-07-22 06:37:03 +08:00
|
|
|
} else if (Feature == "+avx512cd") {
|
|
|
|
HasAVX512CD = true;
|
|
|
|
} else if (Feature == "+avx512vpopcntdq") {
|
|
|
|
HasAVX512VPOPCNTDQ = true;
|
2017-12-27 18:37:51 +08:00
|
|
|
} else if (Feature == "+avx512vnni") {
|
|
|
|
HasAVX512VNNI = true;
|
Enable intrinsics of AVX512_BF16, which are supported for BFLOAT16 in Cooper Lake
Summary:
1. Enable infrastructure of AVX512_BF16, which is supported for BFLOAT16 in Cooper Lake;
2. Enable intrinsics for VCVTNE2PS2BF16, VCVTNEPS2BF16 and DPBF16PS instructions, which are Vector Neural Network Instructions supporting BFLOAT16 inputs and conversion instructions from IEEE single precision.
For more details about BF16 intrinsic, please refer to the latest ISE document: https://software.intel.com/en-us/download/intel-architecture-instruction-set-extensions-programming-reference
Patch by LiuTianle
Reviewers: craig.topper, smaslov, LuoYuanke, wxiao3, annita.zhang, spatel, RKSimon
Reviewed By: craig.topper
Subscribers: mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60552
llvm-svn: 360018
2019-05-06 16:25:11 +08:00
|
|
|
} else if (Feature == "+avx512bf16") {
|
|
|
|
HasAVX512BF16 = true;
|
2017-07-22 06:37:03 +08:00
|
|
|
} else if (Feature == "+avx512er") {
|
|
|
|
HasAVX512ER = true;
|
|
|
|
} else if (Feature == "+avx512pf") {
|
|
|
|
HasAVX512PF = true;
|
|
|
|
} else if (Feature == "+avx512dq") {
|
|
|
|
HasAVX512DQ = true;
|
2017-12-27 18:01:00 +08:00
|
|
|
} else if (Feature == "+avx512bitalg") {
|
|
|
|
HasAVX512BITALG = true;
|
2017-07-22 06:37:03 +08:00
|
|
|
} else if (Feature == "+avx512bw") {
|
|
|
|
HasAVX512BW = true;
|
|
|
|
} else if (Feature == "+avx512vl") {
|
|
|
|
HasAVX512VL = true;
|
|
|
|
} else if (Feature == "+avx512vbmi") {
|
|
|
|
HasAVX512VBMI = true;
|
[x86][icelake][vbmi2]
added vbmi2 feature recognition
added intrinsics support for vbmi2 instructions
_mm[128,256,512]_mask[z]_compress_epi[16,32]
_mm[128,256,512]_mask_compressstoreu_epi[16,32]
_mm[128,256,512]_mask[z]_expand_epi[16,32]
_mm[128,256,512]_mask[z]_expandloadu_epi[16,32]
_mm[128,256,512]_mask[z]_sh[l,r]di_epi[16,32,64]
_mm[128,256,512]_mask_sh[l,r]dv_epi[16,32,64]
matching a similar work on the backend (D40206)
Differential Revision: https://reviews.llvm.org/D41557
llvm-svn: 321487
2017-12-27 19:25:07 +08:00
|
|
|
} else if (Feature == "+avx512vbmi2") {
|
|
|
|
HasAVX512VBMI2 = true;
|
2017-07-22 06:37:03 +08:00
|
|
|
} else if (Feature == "+avx512ifma") {
|
|
|
|
HasAVX512IFMA = true;
|
2019-05-31 14:09:35 +08:00
|
|
|
} else if (Feature == "+avx512vp2intersect") {
|
|
|
|
HasAVX512VP2INTERSECT = true;
|
2017-07-22 06:37:03 +08:00
|
|
|
} else if (Feature == "+sha") {
|
|
|
|
HasSHA = true;
|
2017-11-26 20:34:54 +08:00
|
|
|
} else if (Feature == "+shstk") {
|
|
|
|
HasSHSTK = true;
|
2017-07-22 06:37:03 +08:00
|
|
|
} else if (Feature == "+movbe") {
|
|
|
|
HasMOVBE = true;
|
|
|
|
} else if (Feature == "+sgx") {
|
|
|
|
HasSGX = true;
|
2019-03-22 04:36:08 +08:00
|
|
|
} else if (Feature == "+cx8") {
|
|
|
|
HasCX8 = true;
|
2017-07-22 06:37:03 +08:00
|
|
|
} 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;
|
2018-04-12 04:09:09 +08:00
|
|
|
} else if (Feature == "+wbnoinvd") {
|
|
|
|
HasWBNOINVD = true;
|
2017-07-22 06:37:03 +08:00
|
|
|
} else if (Feature == "+prefetchwt1") {
|
|
|
|
HasPREFETCHWT1 = true;
|
|
|
|
} else if (Feature == "+clzero") {
|
|
|
|
HasCLZERO = true;
|
2018-04-13 15:37:24 +08:00
|
|
|
} else if (Feature == "+cldemote") {
|
|
|
|
HasCLDEMOTE = true;
|
2018-01-21 02:36:52 +08:00
|
|
|
} else if (Feature == "+rdpid") {
|
|
|
|
HasRDPID = true;
|
Introduce the "retpoline" x86 mitigation technique for variant #2 of the speculative execution vulnerabilities disclosed today, specifically identified by CVE-2017-5715, "Branch Target Injection", and is one of the two halves to Spectre..
Summary:
First, we need to explain the core of the vulnerability. Note that this
is a very incomplete description, please see the Project Zero blog post
for details:
https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.html
The basis for branch target injection is to direct speculative execution
of the processor to some "gadget" of executable code by poisoning the
prediction of indirect branches with the address of that gadget. The
gadget in turn contains an operation that provides a side channel for
reading data. Most commonly, this will look like a load of secret data
followed by a branch on the loaded value and then a load of some
predictable cache line. The attacker then uses timing of the processors
cache to determine which direction the branch took *in the speculative
execution*, and in turn what one bit of the loaded value was. Due to the
nature of these timing side channels and the branch predictor on Intel
processors, this allows an attacker to leak data only accessible to
a privileged domain (like the kernel) back into an unprivileged domain.
The goal is simple: avoid generating code which contains an indirect
branch that could have its prediction poisoned by an attacker. In many
cases, the compiler can simply use directed conditional branches and
a small search tree. LLVM already has support for lowering switches in
this way and the first step of this patch is to disable jump-table
lowering of switches and introduce a pass to rewrite explicit indirectbr
sequences into a switch over integers.
However, there is no fully general alternative to indirect calls. We
introduce a new construct we call a "retpoline" to implement indirect
calls in a non-speculatable way. It can be thought of loosely as
a trampoline for indirect calls which uses the RET instruction on x86.
Further, we arrange for a specific call->ret sequence which ensures the
processor predicts the return to go to a controlled, known location. The
retpoline then "smashes" the return address pushed onto the stack by the
call with the desired target of the original indirect call. The result
is a predicted return to the next instruction after a call (which can be
used to trap speculative execution within an infinite loop) and an
actual indirect branch to an arbitrary address.
On 64-bit x86 ABIs, this is especially easily done in the compiler by
using a guaranteed scratch register to pass the target into this device.
For 32-bit ABIs there isn't a guaranteed scratch register and so several
different retpoline variants are introduced to use a scratch register if
one is available in the calling convention and to otherwise use direct
stack push/pop sequences to pass the target address.
This "retpoline" mitigation is fully described in the following blog
post: https://support.google.com/faqs/answer/7625886
We also support a target feature that disables emission of the retpoline
thunk by the compiler to allow for custom thunks if users want them.
These are particularly useful in environments like kernels that
routinely do hot-patching on boot and want to hot-patch their thunk to
different code sequences. They can write this custom thunk and use
`-mretpoline-external-thunk` *in addition* to `-mretpoline`. In this
case, on x86-64 thu thunk names must be:
```
__llvm_external_retpoline_r11
```
or on 32-bit:
```
__llvm_external_retpoline_eax
__llvm_external_retpoline_ecx
__llvm_external_retpoline_edx
__llvm_external_retpoline_push
```
And the target of the retpoline is passed in the named register, or in
the case of the `push` suffix on the top of the stack via a `pushl`
instruction.
There is one other important source of indirect branches in x86 ELF
binaries: the PLT. These patches also include support for LLD to
generate PLT entries that perform a retpoline-style indirection.
The only other indirect branches remaining that we are aware of are from
precompiled runtimes (such as crt0.o and similar). The ones we have
found are not really attackable, and so we have not focused on them
here, but eventually these runtimes should also be replicated for
retpoline-ed configurations for completeness.
For kernels or other freestanding or fully static executables, the
compiler switch `-mretpoline` is sufficient to fully mitigate this
particular attack. For dynamic executables, you must compile *all*
libraries with `-mretpoline` and additionally link the dynamic
executable and all shared libraries with LLD and pass `-z retpolineplt`
(or use similar functionality from some other linker). We strongly
recommend also using `-z now` as non-lazy binding allows the
retpoline-mitigated PLT to be substantially smaller.
When manually apply similar transformations to `-mretpoline` to the
Linux kernel we observed very small performance hits to applications
running typical workloads, and relatively minor hits (approximately 2%)
even for extremely syscall-heavy applications. This is largely due to
the small number of indirect branches that occur in performance
sensitive paths of the kernel.
When using these patches on statically linked applications, especially
C++ applications, you should expect to see a much more dramatic
performance hit. For microbenchmarks that are switch, indirect-, or
virtual-call heavy we have seen overheads ranging from 10% to 50%.
However, real-world workloads exhibit substantially lower performance
impact. Notably, techniques such as PGO and ThinLTO dramatically reduce
the impact of hot indirect calls (by speculatively promoting them to
direct calls) and allow optimized search trees to be used to lower
switches. If you need to deploy these techniques in C++ applications, we
*strongly* recommend that you ensure all hot call targets are statically
linked (avoiding PLT indirection) and use both PGO and ThinLTO. Well
tuned servers using all of these techniques saw 5% - 10% overhead from
the use of retpoline.
We will add detailed documentation covering these components in
subsequent patches, but wanted to make the core functionality available
as soon as possible. Happy for more code review, but we'd really like to
get these patches landed and backported ASAP for obvious reasons. We're
planning to backport this to both 6.0 and 5.0 release streams and get
a 5.0 release with just this cherry picked ASAP for distros and vendors.
This patch is the work of a number of people over the past month: Eric, Reid,
Rui, and myself. I'm mailing it out as a single commit due to the time
sensitive nature of landing this and the need to backport it. Huge thanks to
everyone who helped out here, and everyone at Intel who helped out in
discussions about how to craft this. Also, credit goes to Paul Turner (at
Google, but not an LLVM contributor) for much of the underlying retpoline
design.
Reviewers: echristo, rnk, ruiu, craig.topper, DavidKreitzer
Subscribers: sanjoy, emaste, mcrosier, mgorny, mehdi_amini, hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D41723
llvm-svn: 323155
2018-01-23 06:05:25 +08:00
|
|
|
} else if (Feature == "+retpoline-external-thunk") {
|
|
|
|
HasRetpolineExternalThunk = true;
|
2018-02-18 05:04:35 +08:00
|
|
|
} else if (Feature == "+sahf") {
|
|
|
|
HasLAHFSAHF = true;
|
2018-04-21 02:44:33 +08:00
|
|
|
} else if (Feature == "+waitpkg") {
|
|
|
|
HasWAITPKG = true;
|
2018-05-01 18:05:42 +08:00
|
|
|
} else if (Feature == "+movdiri") {
|
|
|
|
HasMOVDIRI = true;
|
|
|
|
} else if (Feature == "+movdir64b") {
|
|
|
|
HasMOVDIR64B = true;
|
2018-05-08 14:49:41 +08:00
|
|
|
} else if (Feature == "+pconfig") {
|
|
|
|
HasPCONFIG = true;
|
2018-05-10 15:28:54 +08:00
|
|
|
} else if (Feature == "+ptwrite") {
|
|
|
|
HasPTWRITE = true;
|
2018-05-25 14:34:42 +08:00
|
|
|
} else if (Feature == "+invpcid") {
|
|
|
|
HasINVPCID = true;
|
2019-06-06 16:28:42 +08:00
|
|
|
} else if (Feature == "+enqcmd") {
|
|
|
|
HasENQCMD = true;
|
2020-07-07 09:50:17 +08:00
|
|
|
} else if (Feature == "+amx-bf16") {
|
|
|
|
HasAMXBF16 = true;
|
|
|
|
} else if (Feature == "+amx-int8") {
|
|
|
|
HasAMXINT8 = true;
|
|
|
|
} else if (Feature == "+amx-tile") {
|
|
|
|
HasAMXTILE = true;
|
2020-04-02 16:15:34 +08:00
|
|
|
} else if (Feature == "+serialize") {
|
|
|
|
HasSERIALIZE = true;
|
2020-04-09 13:15:42 +08:00
|
|
|
} else if (Feature == "+tsxldtrk") {
|
|
|
|
HasTSXLDTRK = true;
|
2017-07-22 06:37:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2019-07-24 21:30:36 +08:00
|
|
|
// Inline assembly supports X86 flag outputs.
|
2019-02-15 03:27:25 +08:00
|
|
|
Builder.defineMacro("__GCC_ASM_FLAG_OUTPUTS__");
|
|
|
|
|
2018-10-09 06:25:20 +08:00
|
|
|
std::string CodeModel = getTargetOpts().CodeModel;
|
|
|
|
if (CodeModel == "default")
|
|
|
|
CodeModel = "small";
|
2020-02-22 15:28:56 +08:00
|
|
|
Builder.defineMacro("__code_model_" + CodeModel + "__");
|
2018-10-09 06:25:20 +08:00
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2019-07-15 02:33:51 +08:00
|
|
|
Builder.defineMacro("__SEG_GS");
|
|
|
|
Builder.defineMacro("__SEG_FS");
|
|
|
|
Builder.defineMacro("__seg_gs", "__attribute__((address_space(256)))");
|
|
|
|
Builder.defineMacro("__seg_fs", "__attribute__((address_space(257)))");
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
// Subtarget options.
|
|
|
|
// FIXME: We are hard-coding the tune parameters based on the CPU, but they
|
|
|
|
// truly should be based on -mtune options.
|
2020-06-10 03:18:08 +08:00
|
|
|
using namespace llvm::X86;
|
2017-07-22 06:37:03 +08:00
|
|
|
switch (CPU) {
|
2020-06-10 03:18:08 +08:00
|
|
|
case CK_None:
|
2017-07-22 06:37:03 +08:00
|
|
|
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:
|
2019-03-20 15:31:18 +08:00
|
|
|
case CK_i686:
|
2017-10-27 07:06:19 +08:00
|
|
|
defineCPUMacros(Builder, "i686");
|
|
|
|
defineCPUMacros(Builder, "pentiumpro");
|
2017-07-22 06:37:03 +08:00
|
|
|
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;
|
2018-04-16 16:10:10 +08:00
|
|
|
case CK_GoldmontPlus:
|
|
|
|
defineCPUMacros(Builder, "goldmont_plus");
|
|
|
|
break;
|
|
|
|
case CK_Tremont:
|
|
|
|
defineCPUMacros(Builder, "tremont");
|
|
|
|
break;
|
2017-07-22 06:37:03 +08:00
|
|
|
case CK_Nehalem:
|
|
|
|
case CK_Westmere:
|
|
|
|
case CK_SandyBridge:
|
|
|
|
case CK_IvyBridge:
|
|
|
|
case CK_Haswell:
|
|
|
|
case CK_Broadwell:
|
|
|
|
case CK_SkylakeClient:
|
2017-11-19 10:55:14 +08:00
|
|
|
case CK_SkylakeServer:
|
2018-11-28 02:05:14 +08:00
|
|
|
case CK_Cascadelake:
|
2019-06-07 16:53:37 +08:00
|
|
|
case CK_Cooperlake:
|
2017-11-19 10:55:14 +08:00
|
|
|
case CK_Cannonlake:
|
2018-04-11 02:58:26 +08:00
|
|
|
case CK_IcelakeClient:
|
|
|
|
case CK_IcelakeServer:
|
2019-08-12 09:29:46 +08:00
|
|
|
case CK_Tigerlake:
|
[X86] Support -march=sapphirerapids
Support -march=sapphirerapids for x86.
Compare with Icelake Server, it includes 14 more new features. They are
amxtile, amxint8, amxbf16, avx512bf16, avx512vp2intersect, cldemote,
enqcmd, movdir64b, movdiri, ptwrite, serialize, shstk, tsxldtrk, waitpkg.
Reviewed By: craig.topper
Differential Revision: https://reviews.llvm.org/D86503
2020-08-25 12:27:02 +08:00
|
|
|
case CK_SapphireRapids:
|
2017-07-22 06:37:03 +08:00
|
|
|
// 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;
|
2017-10-14 02:14:24 +08:00
|
|
|
case CK_KNM:
|
|
|
|
break;
|
2017-07-22 06:37:03 +08:00
|
|
|
case CK_Lakemont:
|
2017-11-01 10:18:49 +08:00
|
|
|
defineCPUMacros(Builder, "i586", /*Tuning*/false);
|
|
|
|
defineCPUMacros(Builder, "pentium", /*Tuning*/false);
|
2017-07-22 06:37:03 +08:00
|
|
|
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;
|
2019-02-27 01:15:36 +08:00
|
|
|
case CK_ZNVER2:
|
|
|
|
defineCPUMacros(Builder, "znver2");
|
|
|
|
break;
|
2017-07-22 06:37:03 +08:00
|
|
|
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__");
|
|
|
|
|
2017-12-27 16:16:54 +08:00
|
|
|
if (HasVAES)
|
|
|
|
Builder.defineMacro("__VAES__");
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
if (HasPCLMUL)
|
|
|
|
Builder.defineMacro("__PCLMUL__");
|
|
|
|
|
2017-12-27 17:00:31 +08:00
|
|
|
if (HasVPCLMULQDQ)
|
|
|
|
Builder.defineMacro("__VPCLMULQDQ__");
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
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__");
|
|
|
|
|
2018-09-29 01:09:51 +08:00
|
|
|
if (HasMOVBE)
|
|
|
|
Builder.defineMacro("__MOVBE__");
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
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__");
|
|
|
|
|
2017-12-27 16:37:47 +08:00
|
|
|
if (HasGFNI)
|
|
|
|
Builder.defineMacro("__GFNI__");
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
if (HasAVX512CD)
|
|
|
|
Builder.defineMacro("__AVX512CD__");
|
|
|
|
if (HasAVX512VPOPCNTDQ)
|
|
|
|
Builder.defineMacro("__AVX512VPOPCNTDQ__");
|
2017-12-27 18:37:51 +08:00
|
|
|
if (HasAVX512VNNI)
|
|
|
|
Builder.defineMacro("__AVX512VNNI__");
|
Enable intrinsics of AVX512_BF16, which are supported for BFLOAT16 in Cooper Lake
Summary:
1. Enable infrastructure of AVX512_BF16, which is supported for BFLOAT16 in Cooper Lake;
2. Enable intrinsics for VCVTNE2PS2BF16, VCVTNEPS2BF16 and DPBF16PS instructions, which are Vector Neural Network Instructions supporting BFLOAT16 inputs and conversion instructions from IEEE single precision.
For more details about BF16 intrinsic, please refer to the latest ISE document: https://software.intel.com/en-us/download/intel-architecture-instruction-set-extensions-programming-reference
Patch by LiuTianle
Reviewers: craig.topper, smaslov, LuoYuanke, wxiao3, annita.zhang, spatel, RKSimon
Reviewed By: craig.topper
Subscribers: mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60552
llvm-svn: 360018
2019-05-06 16:25:11 +08:00
|
|
|
if (HasAVX512BF16)
|
|
|
|
Builder.defineMacro("__AVX512BF16__");
|
2017-07-22 06:37:03 +08:00
|
|
|
if (HasAVX512ER)
|
|
|
|
Builder.defineMacro("__AVX512ER__");
|
|
|
|
if (HasAVX512PF)
|
|
|
|
Builder.defineMacro("__AVX512PF__");
|
|
|
|
if (HasAVX512DQ)
|
|
|
|
Builder.defineMacro("__AVX512DQ__");
|
2017-12-27 18:01:00 +08:00
|
|
|
if (HasAVX512BITALG)
|
|
|
|
Builder.defineMacro("__AVX512BITALG__");
|
2017-07-22 06:37:03 +08:00
|
|
|
if (HasAVX512BW)
|
|
|
|
Builder.defineMacro("__AVX512BW__");
|
|
|
|
if (HasAVX512VL)
|
|
|
|
Builder.defineMacro("__AVX512VL__");
|
|
|
|
if (HasAVX512VBMI)
|
|
|
|
Builder.defineMacro("__AVX512VBMI__");
|
[x86][icelake][vbmi2]
added vbmi2 feature recognition
added intrinsics support for vbmi2 instructions
_mm[128,256,512]_mask[z]_compress_epi[16,32]
_mm[128,256,512]_mask_compressstoreu_epi[16,32]
_mm[128,256,512]_mask[z]_expand_epi[16,32]
_mm[128,256,512]_mask[z]_expandloadu_epi[16,32]
_mm[128,256,512]_mask[z]_sh[l,r]di_epi[16,32,64]
_mm[128,256,512]_mask_sh[l,r]dv_epi[16,32,64]
matching a similar work on the backend (D40206)
Differential Revision: https://reviews.llvm.org/D41557
llvm-svn: 321487
2017-12-27 19:25:07 +08:00
|
|
|
if (HasAVX512VBMI2)
|
|
|
|
Builder.defineMacro("__AVX512VBMI2__");
|
2017-07-22 06:37:03 +08:00
|
|
|
if (HasAVX512IFMA)
|
|
|
|
Builder.defineMacro("__AVX512IFMA__");
|
2019-05-31 14:09:35 +08:00
|
|
|
if (HasAVX512VP2INTERSECT)
|
|
|
|
Builder.defineMacro("__AVX512VP2INTERSECT__");
|
2017-07-22 06:37:03 +08:00
|
|
|
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 (HasCLFLUSHOPT)
|
|
|
|
Builder.defineMacro("__CLFLUSHOPT__");
|
|
|
|
if (HasCLWB)
|
|
|
|
Builder.defineMacro("__CLWB__");
|
2018-04-12 04:09:09 +08:00
|
|
|
if (HasWBNOINVD)
|
|
|
|
Builder.defineMacro("__WBNOINVD__");
|
2017-11-26 20:34:54 +08:00
|
|
|
if (HasSHSTK)
|
|
|
|
Builder.defineMacro("__SHSTK__");
|
2017-07-22 06:37:03 +08:00
|
|
|
if (HasSGX)
|
|
|
|
Builder.defineMacro("__SGX__");
|
|
|
|
if (HasPREFETCHWT1)
|
|
|
|
Builder.defineMacro("__PREFETCHWT1__");
|
|
|
|
if (HasCLZERO)
|
|
|
|
Builder.defineMacro("__CLZERO__");
|
2018-01-21 02:36:52 +08:00
|
|
|
if (HasRDPID)
|
|
|
|
Builder.defineMacro("__RDPID__");
|
2018-04-13 15:37:24 +08:00
|
|
|
if (HasCLDEMOTE)
|
|
|
|
Builder.defineMacro("__CLDEMOTE__");
|
2018-04-21 02:44:33 +08:00
|
|
|
if (HasWAITPKG)
|
|
|
|
Builder.defineMacro("__WAITPKG__");
|
2018-05-01 18:05:42 +08:00
|
|
|
if (HasMOVDIRI)
|
|
|
|
Builder.defineMacro("__MOVDIRI__");
|
|
|
|
if (HasMOVDIR64B)
|
|
|
|
Builder.defineMacro("__MOVDIR64B__");
|
2018-05-08 14:49:41 +08:00
|
|
|
if (HasPCONFIG)
|
|
|
|
Builder.defineMacro("__PCONFIG__");
|
2018-05-10 15:28:54 +08:00
|
|
|
if (HasPTWRITE)
|
|
|
|
Builder.defineMacro("__PTWRITE__");
|
2018-05-25 14:34:42 +08:00
|
|
|
if (HasINVPCID)
|
|
|
|
Builder.defineMacro("__INVPCID__");
|
2019-06-06 16:28:42 +08:00
|
|
|
if (HasENQCMD)
|
|
|
|
Builder.defineMacro("__ENQCMD__");
|
2020-07-07 09:50:17 +08:00
|
|
|
if (HasAMXTILE)
|
|
|
|
Builder.defineMacro("__AMXTILE__");
|
|
|
|
if (HasAMXINT8)
|
|
|
|
Builder.defineMacro("__AMXINT8__");
|
|
|
|
if (HasAMXBF16)
|
|
|
|
Builder.defineMacro("__AMXBF16__");
|
2020-04-02 16:15:34 +08:00
|
|
|
if (HasSERIALIZE)
|
|
|
|
Builder.defineMacro("__SERIALIZE__");
|
2020-04-09 13:15:42 +08:00
|
|
|
if (HasTSXLDTRK)
|
|
|
|
Builder.defineMacro("__TSXLDTRK__");
|
2017-07-22 06:37:03 +08:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2020-06-10 03:18:08 +08:00
|
|
|
if (CPU >= CK_i486 || CPU == CK_None) {
|
2017-07-22 06:37:03 +08:00
|
|
|
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");
|
|
|
|
}
|
2019-03-22 04:36:08 +08:00
|
|
|
if (HasCX8)
|
2017-07-22 06:37:03 +08:00
|
|
|
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
|
2019-03-14 13:45:42 +08:00
|
|
|
if (HasCX16 && getTriple().getArch() == llvm::Triple::x86_64)
|
2018-01-21 02:36:06 +08:00
|
|
|
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
|
2017-07-22 06:37:03 +08:00
|
|
|
|
|
|
|
if (HasFloat128)
|
|
|
|
Builder.defineMacro("__SIZEOF_FLOAT128__", "16");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
|
|
|
|
return llvm::StringSwitch<bool>(Name)
|
2017-11-07 04:33:13 +08:00
|
|
|
.Case("3dnow", true)
|
|
|
|
.Case("3dnowa", true)
|
2017-12-22 07:27:36 +08:00
|
|
|
.Case("adx", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("aes", true)
|
2020-07-07 09:50:17 +08:00
|
|
|
.Case("amx-bf16", true)
|
|
|
|
.Case("amx-int8", true)
|
|
|
|
.Case("amx-tile", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("avx", true)
|
|
|
|
.Case("avx2", true)
|
|
|
|
.Case("avx512f", true)
|
|
|
|
.Case("avx512cd", true)
|
|
|
|
.Case("avx512vpopcntdq", true)
|
2017-12-27 18:37:51 +08:00
|
|
|
.Case("avx512vnni", true)
|
Enable intrinsics of AVX512_BF16, which are supported for BFLOAT16 in Cooper Lake
Summary:
1. Enable infrastructure of AVX512_BF16, which is supported for BFLOAT16 in Cooper Lake;
2. Enable intrinsics for VCVTNE2PS2BF16, VCVTNEPS2BF16 and DPBF16PS instructions, which are Vector Neural Network Instructions supporting BFLOAT16 inputs and conversion instructions from IEEE single precision.
For more details about BF16 intrinsic, please refer to the latest ISE document: https://software.intel.com/en-us/download/intel-architecture-instruction-set-extensions-programming-reference
Patch by LiuTianle
Reviewers: craig.topper, smaslov, LuoYuanke, wxiao3, annita.zhang, spatel, RKSimon
Reviewed By: craig.topper
Subscribers: mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60552
llvm-svn: 360018
2019-05-06 16:25:11 +08:00
|
|
|
.Case("avx512bf16", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("avx512er", true)
|
|
|
|
.Case("avx512pf", true)
|
|
|
|
.Case("avx512dq", true)
|
2017-12-27 18:01:00 +08:00
|
|
|
.Case("avx512bitalg", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("avx512bw", true)
|
|
|
|
.Case("avx512vl", true)
|
|
|
|
.Case("avx512vbmi", true)
|
[x86][icelake][vbmi2]
added vbmi2 feature recognition
added intrinsics support for vbmi2 instructions
_mm[128,256,512]_mask[z]_compress_epi[16,32]
_mm[128,256,512]_mask_compressstoreu_epi[16,32]
_mm[128,256,512]_mask[z]_expand_epi[16,32]
_mm[128,256,512]_mask[z]_expandloadu_epi[16,32]
_mm[128,256,512]_mask[z]_sh[l,r]di_epi[16,32,64]
_mm[128,256,512]_mask_sh[l,r]dv_epi[16,32,64]
matching a similar work on the backend (D40206)
Differential Revision: https://reviews.llvm.org/D41557
llvm-svn: 321487
2017-12-27 19:25:07 +08:00
|
|
|
.Case("avx512vbmi2", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("avx512ifma", true)
|
2019-05-31 14:09:35 +08:00
|
|
|
.Case("avx512vp2intersect", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("bmi", true)
|
|
|
|
.Case("bmi2", true)
|
2018-04-13 15:37:24 +08:00
|
|
|
.Case("cldemote", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("clflushopt", true)
|
|
|
|
.Case("clwb", true)
|
|
|
|
.Case("clzero", true)
|
|
|
|
.Case("cx16", true)
|
2019-06-06 16:28:42 +08:00
|
|
|
.Case("enqcmd", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("f16c", true)
|
|
|
|
.Case("fma", true)
|
|
|
|
.Case("fma4", true)
|
|
|
|
.Case("fsgsbase", true)
|
|
|
|
.Case("fxsr", true)
|
2017-12-27 16:37:47 +08:00
|
|
|
.Case("gfni", true)
|
2018-05-25 14:34:42 +08:00
|
|
|
.Case("invpcid", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("lwp", true)
|
|
|
|
.Case("lzcnt", true)
|
|
|
|
.Case("mmx", true)
|
|
|
|
.Case("movbe", true)
|
2018-05-01 18:05:42 +08:00
|
|
|
.Case("movdiri", true)
|
|
|
|
.Case("movdir64b", true)
|
2017-12-22 07:27:36 +08:00
|
|
|
.Case("mwaitx", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("pclmul", true)
|
2018-05-08 14:49:41 +08:00
|
|
|
.Case("pconfig", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("pku", true)
|
|
|
|
.Case("popcnt", true)
|
|
|
|
.Case("prefetchwt1", true)
|
|
|
|
.Case("prfchw", true)
|
2018-05-10 15:28:54 +08:00
|
|
|
.Case("ptwrite", true)
|
2018-01-21 02:36:52 +08:00
|
|
|
.Case("rdpid", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("rdrnd", true)
|
|
|
|
.Case("rdseed", true)
|
|
|
|
.Case("rtm", true)
|
2018-02-18 05:04:35 +08:00
|
|
|
.Case("sahf", true)
|
2020-04-02 16:15:34 +08:00
|
|
|
.Case("serialize", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("sgx", true)
|
|
|
|
.Case("sha", true)
|
2017-12-22 07:27:36 +08:00
|
|
|
.Case("shstk", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("sse", true)
|
|
|
|
.Case("sse2", true)
|
|
|
|
.Case("sse3", true)
|
|
|
|
.Case("ssse3", true)
|
2017-10-27 08:18:16 +08:00
|
|
|
.Case("sse4", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("sse4.1", true)
|
|
|
|
.Case("sse4.2", true)
|
|
|
|
.Case("sse4a", true)
|
|
|
|
.Case("tbm", true)
|
2020-04-09 13:15:42 +08:00
|
|
|
.Case("tsxldtrk", true)
|
2017-12-27 16:16:54 +08:00
|
|
|
.Case("vaes", true)
|
2017-12-27 17:00:31 +08:00
|
|
|
.Case("vpclmulqdq", true)
|
2018-04-12 04:09:09 +08:00
|
|
|
.Case("wbnoinvd", true)
|
2018-04-21 02:44:33 +08:00
|
|
|
.Case("waitpkg", true)
|
2017-10-28 02:32:23 +08:00
|
|
|
.Case("x87", true)
|
2017-07-22 06:37:03 +08:00
|
|
|
.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)
|
2017-12-22 07:27:36 +08:00
|
|
|
.Case("adx", HasADX)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("aes", HasAES)
|
2020-07-07 09:50:17 +08:00
|
|
|
.Case("amx-bf16", HasAMXBF16)
|
|
|
|
.Case("amx-int8", HasAMXINT8)
|
|
|
|
.Case("amx-tile", HasAMXTILE)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("avx", SSELevel >= AVX)
|
|
|
|
.Case("avx2", SSELevel >= AVX2)
|
|
|
|
.Case("avx512f", SSELevel >= AVX512F)
|
|
|
|
.Case("avx512cd", HasAVX512CD)
|
|
|
|
.Case("avx512vpopcntdq", HasAVX512VPOPCNTDQ)
|
2017-12-27 18:37:51 +08:00
|
|
|
.Case("avx512vnni", HasAVX512VNNI)
|
Enable intrinsics of AVX512_BF16, which are supported for BFLOAT16 in Cooper Lake
Summary:
1. Enable infrastructure of AVX512_BF16, which is supported for BFLOAT16 in Cooper Lake;
2. Enable intrinsics for VCVTNE2PS2BF16, VCVTNEPS2BF16 and DPBF16PS instructions, which are Vector Neural Network Instructions supporting BFLOAT16 inputs and conversion instructions from IEEE single precision.
For more details about BF16 intrinsic, please refer to the latest ISE document: https://software.intel.com/en-us/download/intel-architecture-instruction-set-extensions-programming-reference
Patch by LiuTianle
Reviewers: craig.topper, smaslov, LuoYuanke, wxiao3, annita.zhang, spatel, RKSimon
Reviewed By: craig.topper
Subscribers: mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60552
llvm-svn: 360018
2019-05-06 16:25:11 +08:00
|
|
|
.Case("avx512bf16", HasAVX512BF16)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("avx512er", HasAVX512ER)
|
|
|
|
.Case("avx512pf", HasAVX512PF)
|
|
|
|
.Case("avx512dq", HasAVX512DQ)
|
2017-12-27 18:01:00 +08:00
|
|
|
.Case("avx512bitalg", HasAVX512BITALG)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("avx512bw", HasAVX512BW)
|
|
|
|
.Case("avx512vl", HasAVX512VL)
|
|
|
|
.Case("avx512vbmi", HasAVX512VBMI)
|
[x86][icelake][vbmi2]
added vbmi2 feature recognition
added intrinsics support for vbmi2 instructions
_mm[128,256,512]_mask[z]_compress_epi[16,32]
_mm[128,256,512]_mask_compressstoreu_epi[16,32]
_mm[128,256,512]_mask[z]_expand_epi[16,32]
_mm[128,256,512]_mask[z]_expandloadu_epi[16,32]
_mm[128,256,512]_mask[z]_sh[l,r]di_epi[16,32,64]
_mm[128,256,512]_mask_sh[l,r]dv_epi[16,32,64]
matching a similar work on the backend (D40206)
Differential Revision: https://reviews.llvm.org/D41557
llvm-svn: 321487
2017-12-27 19:25:07 +08:00
|
|
|
.Case("avx512vbmi2", HasAVX512VBMI2)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("avx512ifma", HasAVX512IFMA)
|
2019-05-31 14:09:35 +08:00
|
|
|
.Case("avx512vp2intersect", HasAVX512VP2INTERSECT)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("bmi", HasBMI)
|
|
|
|
.Case("bmi2", HasBMI2)
|
2018-04-13 15:37:24 +08:00
|
|
|
.Case("cldemote", HasCLDEMOTE)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("clflushopt", HasCLFLUSHOPT)
|
|
|
|
.Case("clwb", HasCLWB)
|
|
|
|
.Case("clzero", HasCLZERO)
|
2019-03-22 04:36:08 +08:00
|
|
|
.Case("cx8", HasCX8)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("cx16", HasCX16)
|
2019-06-06 16:28:42 +08:00
|
|
|
.Case("enqcmd", HasENQCMD)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("f16c", HasF16C)
|
|
|
|
.Case("fma", HasFMA)
|
|
|
|
.Case("fma4", XOPLevel >= FMA4)
|
|
|
|
.Case("fsgsbase", HasFSGSBASE)
|
|
|
|
.Case("fxsr", HasFXSR)
|
2017-12-27 16:37:47 +08:00
|
|
|
.Case("gfni", HasGFNI)
|
2018-05-25 14:34:42 +08:00
|
|
|
.Case("invpcid", HasINVPCID)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("lwp", HasLWP)
|
|
|
|
.Case("lzcnt", HasLZCNT)
|
|
|
|
.Case("mm3dnow", MMX3DNowLevel >= AMD3DNow)
|
|
|
|
.Case("mm3dnowa", MMX3DNowLevel >= AMD3DNowAthlon)
|
|
|
|
.Case("mmx", MMX3DNowLevel >= MMX)
|
|
|
|
.Case("movbe", HasMOVBE)
|
2018-05-01 18:05:42 +08:00
|
|
|
.Case("movdiri", HasMOVDIRI)
|
|
|
|
.Case("movdir64b", HasMOVDIR64B)
|
2017-12-22 07:27:36 +08:00
|
|
|
.Case("mwaitx", HasMWAITX)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("pclmul", HasPCLMUL)
|
2018-05-08 14:49:41 +08:00
|
|
|
.Case("pconfig", HasPCONFIG)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("pku", HasPKU)
|
|
|
|
.Case("popcnt", HasPOPCNT)
|
|
|
|
.Case("prefetchwt1", HasPREFETCHWT1)
|
|
|
|
.Case("prfchw", HasPRFCHW)
|
2018-05-10 15:28:54 +08:00
|
|
|
.Case("ptwrite", HasPTWRITE)
|
2018-01-21 02:36:52 +08:00
|
|
|
.Case("rdpid", HasRDPID)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("rdrnd", HasRDRND)
|
|
|
|
.Case("rdseed", HasRDSEED)
|
Introduce the "retpoline" x86 mitigation technique for variant #2 of the speculative execution vulnerabilities disclosed today, specifically identified by CVE-2017-5715, "Branch Target Injection", and is one of the two halves to Spectre..
Summary:
First, we need to explain the core of the vulnerability. Note that this
is a very incomplete description, please see the Project Zero blog post
for details:
https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.html
The basis for branch target injection is to direct speculative execution
of the processor to some "gadget" of executable code by poisoning the
prediction of indirect branches with the address of that gadget. The
gadget in turn contains an operation that provides a side channel for
reading data. Most commonly, this will look like a load of secret data
followed by a branch on the loaded value and then a load of some
predictable cache line. The attacker then uses timing of the processors
cache to determine which direction the branch took *in the speculative
execution*, and in turn what one bit of the loaded value was. Due to the
nature of these timing side channels and the branch predictor on Intel
processors, this allows an attacker to leak data only accessible to
a privileged domain (like the kernel) back into an unprivileged domain.
The goal is simple: avoid generating code which contains an indirect
branch that could have its prediction poisoned by an attacker. In many
cases, the compiler can simply use directed conditional branches and
a small search tree. LLVM already has support for lowering switches in
this way and the first step of this patch is to disable jump-table
lowering of switches and introduce a pass to rewrite explicit indirectbr
sequences into a switch over integers.
However, there is no fully general alternative to indirect calls. We
introduce a new construct we call a "retpoline" to implement indirect
calls in a non-speculatable way. It can be thought of loosely as
a trampoline for indirect calls which uses the RET instruction on x86.
Further, we arrange for a specific call->ret sequence which ensures the
processor predicts the return to go to a controlled, known location. The
retpoline then "smashes" the return address pushed onto the stack by the
call with the desired target of the original indirect call. The result
is a predicted return to the next instruction after a call (which can be
used to trap speculative execution within an infinite loop) and an
actual indirect branch to an arbitrary address.
On 64-bit x86 ABIs, this is especially easily done in the compiler by
using a guaranteed scratch register to pass the target into this device.
For 32-bit ABIs there isn't a guaranteed scratch register and so several
different retpoline variants are introduced to use a scratch register if
one is available in the calling convention and to otherwise use direct
stack push/pop sequences to pass the target address.
This "retpoline" mitigation is fully described in the following blog
post: https://support.google.com/faqs/answer/7625886
We also support a target feature that disables emission of the retpoline
thunk by the compiler to allow for custom thunks if users want them.
These are particularly useful in environments like kernels that
routinely do hot-patching on boot and want to hot-patch their thunk to
different code sequences. They can write this custom thunk and use
`-mretpoline-external-thunk` *in addition* to `-mretpoline`. In this
case, on x86-64 thu thunk names must be:
```
__llvm_external_retpoline_r11
```
or on 32-bit:
```
__llvm_external_retpoline_eax
__llvm_external_retpoline_ecx
__llvm_external_retpoline_edx
__llvm_external_retpoline_push
```
And the target of the retpoline is passed in the named register, or in
the case of the `push` suffix on the top of the stack via a `pushl`
instruction.
There is one other important source of indirect branches in x86 ELF
binaries: the PLT. These patches also include support for LLD to
generate PLT entries that perform a retpoline-style indirection.
The only other indirect branches remaining that we are aware of are from
precompiled runtimes (such as crt0.o and similar). The ones we have
found are not really attackable, and so we have not focused on them
here, but eventually these runtimes should also be replicated for
retpoline-ed configurations for completeness.
For kernels or other freestanding or fully static executables, the
compiler switch `-mretpoline` is sufficient to fully mitigate this
particular attack. For dynamic executables, you must compile *all*
libraries with `-mretpoline` and additionally link the dynamic
executable and all shared libraries with LLD and pass `-z retpolineplt`
(or use similar functionality from some other linker). We strongly
recommend also using `-z now` as non-lazy binding allows the
retpoline-mitigated PLT to be substantially smaller.
When manually apply similar transformations to `-mretpoline` to the
Linux kernel we observed very small performance hits to applications
running typical workloads, and relatively minor hits (approximately 2%)
even for extremely syscall-heavy applications. This is largely due to
the small number of indirect branches that occur in performance
sensitive paths of the kernel.
When using these patches on statically linked applications, especially
C++ applications, you should expect to see a much more dramatic
performance hit. For microbenchmarks that are switch, indirect-, or
virtual-call heavy we have seen overheads ranging from 10% to 50%.
However, real-world workloads exhibit substantially lower performance
impact. Notably, techniques such as PGO and ThinLTO dramatically reduce
the impact of hot indirect calls (by speculatively promoting them to
direct calls) and allow optimized search trees to be used to lower
switches. If you need to deploy these techniques in C++ applications, we
*strongly* recommend that you ensure all hot call targets are statically
linked (avoiding PLT indirection) and use both PGO and ThinLTO. Well
tuned servers using all of these techniques saw 5% - 10% overhead from
the use of retpoline.
We will add detailed documentation covering these components in
subsequent patches, but wanted to make the core functionality available
as soon as possible. Happy for more code review, but we'd really like to
get these patches landed and backported ASAP for obvious reasons. We're
planning to backport this to both 6.0 and 5.0 release streams and get
a 5.0 release with just this cherry picked ASAP for distros and vendors.
This patch is the work of a number of people over the past month: Eric, Reid,
Rui, and myself. I'm mailing it out as a single commit due to the time
sensitive nature of landing this and the need to backport it. Huge thanks to
everyone who helped out here, and everyone at Intel who helped out in
discussions about how to craft this. Also, credit goes to Paul Turner (at
Google, but not an LLVM contributor) for much of the underlying retpoline
design.
Reviewers: echristo, rnk, ruiu, craig.topper, DavidKreitzer
Subscribers: sanjoy, emaste, mcrosier, mgorny, mehdi_amini, hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D41723
llvm-svn: 323155
2018-01-23 06:05:25 +08:00
|
|
|
.Case("retpoline-external-thunk", HasRetpolineExternalThunk)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("rtm", HasRTM)
|
2018-02-18 05:04:35 +08:00
|
|
|
.Case("sahf", HasLAHFSAHF)
|
2020-04-02 16:15:34 +08:00
|
|
|
.Case("serialize", HasSERIALIZE)
|
2017-07-22 06:37:03 +08:00
|
|
|
.Case("sgx", HasSGX)
|
|
|
|
.Case("sha", HasSHA)
|
2017-12-22 07:27:36 +08:00
|
|
|
.Case("shstk", HasSHSTK)
|
2017-07-22 06:37:03 +08:00
|
|
|
.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)
|
2020-04-09 13:15:42 +08:00
|
|
|
.Case("tsxldtrk", HasTSXLDTRK)
|
2017-12-27 16:16:54 +08:00
|
|
|
.Case("vaes", HasVAES)
|
2017-12-27 17:00:31 +08:00
|
|
|
.Case("vpclmulqdq", HasVPCLMULQDQ)
|
2018-04-12 04:09:09 +08:00
|
|
|
.Case("wbnoinvd", HasWBNOINVD)
|
2018-04-21 02:44:33 +08:00
|
|
|
.Case("waitpkg", HasWAITPKG)
|
2017-07-22 06:37:03 +08:00
|
|
|
.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)
|
2020-06-22 11:20:04 +08:00
|
|
|
#define X86_FEATURE_COMPAT(ENUM, STR) .Case(STR, true)
|
2017-11-22 08:54:01 +08:00
|
|
|
#include "llvm/Support/X86TargetParser.def"
|
2017-07-22 06:37:03 +08:00
|
|
|
.Default(false);
|
|
|
|
}
|
|
|
|
|
Implement Attribute Target MultiVersioning
GCC's attribute 'target', in addition to being an optimization hint,
also allows function multiversioning. We currently have the former
implemented, this is the latter's implementation.
This works by enabling functions with the same name/signature to coexist,
so that they can all be emitted. Multiversion state is stored in the
FunctionDecl itself, and SemaDecl manages the definitions.
Note that it ends up having to permit redefinition of functions so
that they can all be emitted. Additionally, all versions of the function
must be emitted, so this also manages that.
Note that this includes some additional rules that GCC does not, since
defining something as a MultiVersion function after a usage has been made illegal.
The only 'history rewriting' that happens is if a function is emitted before
it has been converted to a multiversion'ed function, at which point its name
needs to be changed.
Function templates and virtual functions are NOT yet supported (not supported
in GCC either).
Additionally, constructors/destructors are disallowed, but the former is
planned.
llvm-svn: 322028
2018-01-09 05:34:17 +08:00
|
|
|
static llvm::X86::ProcessorFeatures getFeature(StringRef Name) {
|
|
|
|
return llvm::StringSwitch<llvm::X86::ProcessorFeatures>(Name)
|
2020-07-01 02:59:03 +08:00
|
|
|
#define X86_FEATURE_COMPAT(ENUM, STR) .Case(STR, llvm::X86::FEATURE_##ENUM)
|
Implement Attribute Target MultiVersioning
GCC's attribute 'target', in addition to being an optimization hint,
also allows function multiversioning. We currently have the former
implemented, this is the latter's implementation.
This works by enabling functions with the same name/signature to coexist,
so that they can all be emitted. Multiversion state is stored in the
FunctionDecl itself, and SemaDecl manages the definitions.
Note that it ends up having to permit redefinition of functions so
that they can all be emitted. Additionally, all versions of the function
must be emitted, so this also manages that.
Note that this includes some additional rules that GCC does not, since
defining something as a MultiVersion function after a usage has been made illegal.
The only 'history rewriting' that happens is if a function is emitted before
it has been converted to a multiversion'ed function, at which point its name
needs to be changed.
Function templates and virtual functions are NOT yet supported (not supported
in GCC either).
Additionally, constructors/destructors are disallowed, but the former is
planned.
llvm-svn: 322028
2018-01-09 05:34:17 +08:00
|
|
|
#include "llvm/Support/X86TargetParser.def"
|
|
|
|
;
|
|
|
|
// Note, this function should only be used after ensuring the value is
|
|
|
|
// correct, so it asserts if the value is out of range.
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned getFeaturePriority(llvm::X86::ProcessorFeatures Feat) {
|
|
|
|
enum class FeatPriority {
|
|
|
|
#define FEATURE(FEAT) FEAT,
|
|
|
|
#include "clang/Basic/X86Target.def"
|
|
|
|
};
|
|
|
|
switch (Feat) {
|
|
|
|
#define FEATURE(FEAT) \
|
|
|
|
case llvm::X86::FEAT: \
|
|
|
|
return static_cast<unsigned>(FeatPriority::FEAT);
|
|
|
|
#include "clang/Basic/X86Target.def"
|
|
|
|
default:
|
|
|
|
llvm_unreachable("No Feature Priority for non-CPUSupports Features");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned X86TargetInfo::multiVersionSortPriority(StringRef Name) const {
|
|
|
|
// Valid CPUs have a 'key feature' that compares just better than its key
|
|
|
|
// feature.
|
2020-06-10 03:18:08 +08:00
|
|
|
using namespace llvm::X86;
|
|
|
|
CPUKind Kind = parseArchX86(Name);
|
|
|
|
if (Kind != CK_None) {
|
2020-06-25 01:36:02 +08:00
|
|
|
ProcessorFeatures KeyFeature = getKeyFeature(Kind);
|
|
|
|
return (getFeaturePriority(KeyFeature) << 1) + 1;
|
Implement Attribute Target MultiVersioning
GCC's attribute 'target', in addition to being an optimization hint,
also allows function multiversioning. We currently have the former
implemented, this is the latter's implementation.
This works by enabling functions with the same name/signature to coexist,
so that they can all be emitted. Multiversion state is stored in the
FunctionDecl itself, and SemaDecl manages the definitions.
Note that it ends up having to permit redefinition of functions so
that they can all be emitted. Additionally, all versions of the function
must be emitted, so this also manages that.
Note that this includes some additional rules that GCC does not, since
defining something as a MultiVersion function after a usage has been made illegal.
The only 'history rewriting' that happens is if a function is emitted before
it has been converted to a multiversion'ed function, at which point its name
needs to be changed.
Function templates and virtual functions are NOT yet supported (not supported
in GCC either).
Additionally, constructors/destructors are disallowed, but the former is
planned.
llvm-svn: 322028
2018-01-09 05:34:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now we know we have a feature, so get its priority and shift it a few so
|
|
|
|
// that we have sufficient room for the CPUs (above).
|
|
|
|
return getFeaturePriority(getFeature(Name)) << 1;
|
|
|
|
}
|
|
|
|
|
2018-07-20 22:13:28 +08:00
|
|
|
bool X86TargetInfo::validateCPUSpecificCPUDispatch(StringRef Name) const {
|
|
|
|
return llvm::StringSwitch<bool>(Name)
|
|
|
|
#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) .Case(NAME, true)
|
|
|
|
#define CPU_SPECIFIC_ALIAS(NEW_NAME, NAME) .Case(NEW_NAME, true)
|
|
|
|
#include "clang/Basic/X86Target.def"
|
|
|
|
.Default(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static StringRef CPUSpecificCPUDispatchNameDealias(StringRef Name) {
|
|
|
|
return llvm::StringSwitch<StringRef>(Name)
|
|
|
|
#define CPU_SPECIFIC_ALIAS(NEW_NAME, NAME) .Case(NEW_NAME, NAME)
|
|
|
|
#include "clang/Basic/X86Target.def"
|
|
|
|
.Default(Name);
|
|
|
|
}
|
|
|
|
|
|
|
|
char X86TargetInfo::CPUSpecificManglingCharacter(StringRef Name) const {
|
|
|
|
return llvm::StringSwitch<char>(CPUSpecificCPUDispatchNameDealias(Name))
|
|
|
|
#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) .Case(NAME, MANGLING)
|
|
|
|
#include "clang/Basic/X86Target.def"
|
|
|
|
.Default(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void X86TargetInfo::getCPUSpecificCPUDispatchFeatures(
|
|
|
|
StringRef Name, llvm::SmallVectorImpl<StringRef> &Features) const {
|
|
|
|
StringRef WholeList =
|
|
|
|
llvm::StringSwitch<StringRef>(CPUSpecificCPUDispatchNameDealias(Name))
|
|
|
|
#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) .Case(NAME, FEATURES)
|
|
|
|
#include "clang/Basic/X86Target.def"
|
|
|
|
.Default("");
|
|
|
|
WholeList.split(Features, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
|
|
|
|
}
|
|
|
|
|
2017-08-11 04:28:30 +08:00
|
|
|
// 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)
|
2017-11-15 08:11:24 +08:00
|
|
|
#define X86_VENDOR(ENUM, STRING) .Case(STRING, true)
|
2020-07-13 07:58:27 +08:00
|
|
|
#define X86_CPU_TYPE_ALIAS(ENUM, ALIAS) .Case(ALIAS, true)
|
|
|
|
#define X86_CPU_TYPE(ENUM, STR) .Case(STR, true)
|
|
|
|
#define X86_CPU_SUBTYPE(ENUM, STR) .Case(STR, true)
|
2017-11-15 08:11:24 +08:00
|
|
|
#include "llvm/Support/X86TargetParser.def"
|
2017-08-11 04:28:30 +08:00
|
|
|
.Default(false);
|
|
|
|
}
|
|
|
|
|
2019-02-15 03:27:25 +08:00
|
|
|
static unsigned matchAsmCCConstraint(const char *&Name) {
|
|
|
|
auto RV = llvm::StringSwitch<unsigned>(Name)
|
|
|
|
.Case("@cca", 4)
|
|
|
|
.Case("@ccae", 5)
|
|
|
|
.Case("@ccb", 4)
|
|
|
|
.Case("@ccbe", 5)
|
|
|
|
.Case("@ccc", 4)
|
|
|
|
.Case("@cce", 4)
|
|
|
|
.Case("@ccz", 4)
|
|
|
|
.Case("@ccg", 4)
|
|
|
|
.Case("@ccge", 5)
|
|
|
|
.Case("@ccl", 4)
|
|
|
|
.Case("@ccle", 5)
|
|
|
|
.Case("@ccna", 5)
|
|
|
|
.Case("@ccnae", 6)
|
|
|
|
.Case("@ccnb", 5)
|
|
|
|
.Case("@ccnbe", 6)
|
|
|
|
.Case("@ccnc", 5)
|
|
|
|
.Case("@ccne", 5)
|
|
|
|
.Case("@ccnz", 5)
|
|
|
|
.Case("@ccng", 5)
|
|
|
|
.Case("@ccnge", 6)
|
|
|
|
.Case("@ccnl", 5)
|
|
|
|
.Case("@ccnle", 6)
|
|
|
|
.Case("@ccno", 5)
|
|
|
|
.Case("@ccnp", 5)
|
|
|
|
.Case("@ccns", 5)
|
|
|
|
.Case("@cco", 4)
|
|
|
|
.Case("@ccp", 4)
|
|
|
|
.Case("@ccs", 4)
|
|
|
|
.Default(0);
|
|
|
|
return RV;
|
|
|
|
}
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
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;
|
2020-05-07 05:53:10 +08:00
|
|
|
case 'z': // First SSE register.
|
2017-08-24 17:07:34 +08:00
|
|
|
case '2':
|
2017-07-22 06:37:03 +08:00
|
|
|
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.
|
2018-04-06 23:14:32 +08:00
|
|
|
case 'k': // Any AVX512 mask register (same as Yk, additionally allows k0
|
2017-07-22 06:37:03 +08:00
|
|
|
// 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;
|
2019-02-15 03:27:25 +08:00
|
|
|
case '@':
|
|
|
|
// CC condition changes.
|
|
|
|
if (auto Len = matchAsmCCConstraint(Name)) {
|
|
|
|
Name += Len - 1;
|
|
|
|
Info.setAllowsRegister();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2017-07-22 06:37:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-26 00:48:01 +08:00
|
|
|
// Below is based on the following information:
|
|
|
|
// +------------------------------------+-------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
|
|
// | Processor Name | Cache Line Size (Bytes) | Source |
|
|
|
|
// +------------------------------------+-------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
|
|
// | i386 | 64 | https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf |
|
|
|
|
// | 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) |
|
|
|
|
// | i586/Pentium MMX | 32 | https://www.7-cpu.com/cpu/P-MMX.html |
|
|
|
|
// | i686/Pentium | 32 | https://www.7-cpu.com/cpu/P6.html |
|
|
|
|
// | Netburst/Pentium4 | 64 | https://www.7-cpu.com/cpu/P4-180.html |
|
|
|
|
// | Atom | 64 | https://www.7-cpu.com/cpu/Atom.html |
|
|
|
|
// | Westmere | 64 | https://en.wikichip.org/wiki/intel/microarchitectures/sandy_bridge_(client) "Cache Architecture" |
|
|
|
|
// | Sandy Bridge | 64 | https://en.wikipedia.org/wiki/Sandy_Bridge and https://www.7-cpu.com/cpu/SandyBridge.html |
|
|
|
|
// | Ivy Bridge | 64 | https://blog.stuffedcow.net/2013/01/ivb-cache-replacement/ and https://www.7-cpu.com/cpu/IvyBridge.html |
|
|
|
|
// | Haswell | 64 | https://www.7-cpu.com/cpu/Haswell.html |
|
|
|
|
// | Boadwell | 64 | https://www.7-cpu.com/cpu/Broadwell.html |
|
|
|
|
// | Skylake (including skylake-avx512) | 64 | https://www.nas.nasa.gov/hecc/support/kb/skylake-processors_550.html "Cache Hierarchy" |
|
|
|
|
// | Cascade Lake | 64 | https://www.nas.nasa.gov/hecc/support/kb/cascade-lake-processors_579.html "Cache Hierarchy" |
|
|
|
|
// | Skylake | 64 | https://en.wikichip.org/wiki/intel/microarchitectures/kaby_lake "Memory Hierarchy" |
|
|
|
|
// | Ice Lake | 64 | https://www.7-cpu.com/cpu/Ice_Lake.html |
|
|
|
|
// | 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" |
|
|
|
|
// | 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 " |
|
|
|
|
// +------------------------------------+-------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
|
|
Optional<unsigned> X86TargetInfo::getCPUCacheLineSize() const {
|
2020-06-10 03:18:08 +08:00
|
|
|
using namespace llvm::X86;
|
2020-03-26 00:48:01 +08:00
|
|
|
switch (CPU) {
|
|
|
|
// i386
|
|
|
|
case CK_i386:
|
|
|
|
// i486
|
|
|
|
case CK_i486:
|
|
|
|
case CK_WinChipC6:
|
|
|
|
case CK_WinChip2:
|
|
|
|
case CK_C3:
|
|
|
|
// Lakemont
|
|
|
|
case CK_Lakemont:
|
|
|
|
return 16;
|
|
|
|
|
|
|
|
// i586
|
|
|
|
case CK_i586:
|
|
|
|
case CK_Pentium:
|
|
|
|
case CK_PentiumMMX:
|
|
|
|
// i686
|
|
|
|
case CK_PentiumPro:
|
|
|
|
case CK_i686:
|
|
|
|
case CK_Pentium2:
|
|
|
|
case CK_Pentium3:
|
|
|
|
case CK_PentiumM:
|
|
|
|
case CK_C3_2:
|
|
|
|
// K6
|
|
|
|
case CK_K6:
|
|
|
|
case CK_K6_2:
|
|
|
|
case CK_K6_3:
|
|
|
|
// Geode
|
|
|
|
case CK_Geode:
|
|
|
|
return 32;
|
|
|
|
|
|
|
|
// Netburst
|
|
|
|
case CK_Pentium4:
|
|
|
|
case CK_Prescott:
|
|
|
|
case CK_Nocona:
|
|
|
|
// Atom
|
|
|
|
case CK_Bonnell:
|
|
|
|
case CK_Silvermont:
|
|
|
|
case CK_Goldmont:
|
|
|
|
case CK_GoldmontPlus:
|
|
|
|
case CK_Tremont:
|
|
|
|
|
|
|
|
case CK_Westmere:
|
|
|
|
case CK_SandyBridge:
|
|
|
|
case CK_IvyBridge:
|
|
|
|
case CK_Haswell:
|
|
|
|
case CK_Broadwell:
|
|
|
|
case CK_SkylakeClient:
|
|
|
|
case CK_SkylakeServer:
|
|
|
|
case CK_Cascadelake:
|
|
|
|
case CK_Nehalem:
|
|
|
|
case CK_Cooperlake:
|
|
|
|
case CK_Cannonlake:
|
|
|
|
case CK_Tigerlake:
|
[X86] Support -march=sapphirerapids
Support -march=sapphirerapids for x86.
Compare with Icelake Server, it includes 14 more new features. They are
amxtile, amxint8, amxbf16, avx512bf16, avx512vp2intersect, cldemote,
enqcmd, movdir64b, movdiri, ptwrite, serialize, shstk, tsxldtrk, waitpkg.
Reviewed By: craig.topper
Differential Revision: https://reviews.llvm.org/D86503
2020-08-25 12:27:02 +08:00
|
|
|
case CK_SapphireRapids:
|
2020-03-26 00:48:01 +08:00
|
|
|
case CK_IcelakeClient:
|
|
|
|
case CK_IcelakeServer:
|
|
|
|
case CK_KNL:
|
|
|
|
case CK_KNM:
|
|
|
|
// K7
|
|
|
|
case CK_Athlon:
|
|
|
|
case CK_AthlonXP:
|
|
|
|
// K8
|
|
|
|
case CK_K8:
|
|
|
|
case CK_K8SSE3:
|
|
|
|
case CK_AMDFAM10:
|
|
|
|
// Bobcat
|
|
|
|
case CK_BTVER1:
|
|
|
|
case CK_BTVER2:
|
|
|
|
// Bulldozer
|
|
|
|
case CK_BDVER1:
|
|
|
|
case CK_BDVER2:
|
|
|
|
case CK_BDVER3:
|
|
|
|
case CK_BDVER4:
|
|
|
|
// Zen
|
|
|
|
case CK_ZNVER1:
|
|
|
|
case CK_ZNVER2:
|
|
|
|
// Deprecated
|
|
|
|
case CK_x86_64:
|
|
|
|
case CK_Yonah:
|
|
|
|
case CK_Penryn:
|
|
|
|
case CK_Core2:
|
|
|
|
return 64;
|
|
|
|
|
|
|
|
// The following currently have unknown cache line sizes (but they are probably all 64):
|
|
|
|
// Core
|
2020-06-10 03:18:08 +08:00
|
|
|
case CK_None:
|
2020-03-26 00:48:01 +08:00
|
|
|
return None;
|
|
|
|
}
|
2020-03-27 11:09:14 +08:00
|
|
|
llvm_unreachable("Unknown CPU kind");
|
2020-03-26 00:48:01 +08:00
|
|
|
}
|
|
|
|
|
2019-12-24 02:38:38 +08:00
|
|
|
bool X86TargetInfo::validateOutputSize(const llvm::StringMap<bool> &FeatureMap,
|
|
|
|
StringRef Constraint,
|
2017-07-22 06:37:03 +08:00
|
|
|
unsigned Size) const {
|
|
|
|
// Strip off constraint modifiers.
|
|
|
|
while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
|
|
|
|
Constraint = Constraint.substr(1);
|
|
|
|
|
2019-12-24 02:38:38 +08:00
|
|
|
return validateOperandSize(FeatureMap, Constraint, Size);
|
2017-07-22 06:37:03 +08:00
|
|
|
}
|
|
|
|
|
2019-12-24 02:38:38 +08:00
|
|
|
bool X86TargetInfo::validateInputSize(const llvm::StringMap<bool> &FeatureMap,
|
|
|
|
StringRef Constraint,
|
2017-07-22 06:37:03 +08:00
|
|
|
unsigned Size) const {
|
2019-12-24 02:38:38 +08:00
|
|
|
return validateOperandSize(FeatureMap, Constraint, Size);
|
2017-07-22 06:37:03 +08:00
|
|
|
}
|
|
|
|
|
2019-12-24 02:38:38 +08:00
|
|
|
bool X86TargetInfo::validateOperandSize(const llvm::StringMap<bool> &FeatureMap,
|
|
|
|
StringRef Constraint,
|
2017-07-22 06:37:03 +08:00
|
|
|
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:
|
2017-08-24 17:07:34 +08:00
|
|
|
return false;
|
2017-07-22 06:37:03 +08:00
|
|
|
case 'm':
|
|
|
|
// 'Ym' is synonymous with 'y'.
|
|
|
|
case 'k':
|
|
|
|
return Size <= 64;
|
2017-08-24 17:07:34 +08:00
|
|
|
case 'z':
|
2020-05-06 10:47:39 +08:00
|
|
|
// XMM0/YMM/ZMM0
|
|
|
|
if (FeatureMap.lookup("avx512f"))
|
|
|
|
// ZMM0 can be used if target supports AVX512F.
|
|
|
|
return Size <= 512U;
|
|
|
|
else if (FeatureMap.lookup("avx"))
|
|
|
|
// YMM0 can be used if target supports AVX.
|
|
|
|
return Size <= 256U;
|
|
|
|
else if (FeatureMap.lookup("sse"))
|
2017-08-24 17:07:34 +08:00
|
|
|
return Size <= 128U;
|
|
|
|
return false;
|
2017-07-22 06:37:03 +08:00
|
|
|
case 'i':
|
|
|
|
case 't':
|
2017-08-24 17:07:34 +08:00
|
|
|
case '2':
|
|
|
|
// 'Yi','Yt','Y2' are synonymous with 'x' when SSE2 is enabled.
|
|
|
|
if (SSELevel < SSE2)
|
|
|
|
return false;
|
|
|
|
break;
|
2017-07-22 06:37:03 +08:00
|
|
|
}
|
2020-05-07 05:20:45 +08:00
|
|
|
break;
|
2017-08-24 17:07:34 +08:00
|
|
|
case 'v':
|
|
|
|
case 'x':
|
2019-12-24 02:38:38 +08:00
|
|
|
if (FeatureMap.lookup("avx512f"))
|
2017-08-24 17:07:34 +08:00
|
|
|
// 512-bit zmm registers can be used if target supports AVX512F.
|
|
|
|
return Size <= 512U;
|
2019-12-24 02:38:38 +08:00
|
|
|
else if (FeatureMap.lookup("avx"))
|
2017-08-24 17:07:34 +08:00
|
|
|
// 256-bit ymm registers can be used if target supports AVX.
|
|
|
|
return Size <= 256U;
|
|
|
|
return Size <= 128U;
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string X86TargetInfo::convertConstraint(const char *&Constraint) const {
|
|
|
|
switch (*Constraint) {
|
2019-02-15 03:27:25 +08:00
|
|
|
case '@':
|
|
|
|
if (auto Len = matchAsmCCConstraint(Constraint)) {
|
|
|
|
std::string Converted = "{" + std::string(Constraint, Len) + "}";
|
|
|
|
Constraint += Len - 1;
|
|
|
|
return Converted;
|
|
|
|
}
|
|
|
|
return std::string(1, *Constraint);
|
2017-07-22 06:37:03 +08:00
|
|
|
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':
|
2017-08-24 17:07:34 +08:00
|
|
|
case 'm':
|
|
|
|
case 'i':
|
|
|
|
case 't':
|
|
|
|
case 'z':
|
|
|
|
case '2':
|
2017-07-22 06:37:03 +08:00
|
|
|
// "^" 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-09 07:15:02 +08:00
|
|
|
void X86TargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
|
2020-06-10 03:18:08 +08:00
|
|
|
bool Only64Bit = getTriple().getArch() != llvm::Triple::x86;
|
|
|
|
llvm::X86::fillValidCPUArchList(Values, Only64Bit);
|
2017-07-22 06:37:03 +08:00
|
|
|
}
|
|
|
|
|
2020-08-23 07:05:01 +08:00
|
|
|
void X86TargetInfo::fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const {
|
|
|
|
llvm::X86::fillValidCPUArchList(Values);
|
|
|
|
}
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
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);
|
|
|
|
}
|