summaryrefslogtreecommitdiff
path: root/lib/Target/X86/X86Subtarget.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
commit01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch)
tree4def12e759965de927d963ac65840d663ef9d1ea /lib/Target/X86/X86Subtarget.cpp
parentf0f4822ed4b66e3579e92a89f368f8fb860e218e (diff)
Diffstat (limited to 'lib/Target/X86/X86Subtarget.cpp')
-rw-r--r--lib/Target/X86/X86Subtarget.cpp175
1 files changed, 83 insertions, 92 deletions
diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp
index 8ef08c960f0b7..8f77682d22766 100644
--- a/lib/Target/X86/X86Subtarget.cpp
+++ b/lib/Target/X86/X86Subtarget.cpp
@@ -46,105 +46,99 @@ X86EarlyIfConv("x86-early-ifcvt", cl::Hidden,
/// Classify a blockaddress reference for the current subtarget according to how
/// we should reference it in a non-pcrel context.
-unsigned char X86Subtarget::ClassifyBlockAddressReference() const {
- if (isPICStyleGOT()) // 32-bit ELF targets.
- return X86II::MO_GOTOFF;
-
- if (isPICStyleStubPIC()) // Darwin/32 in PIC mode.
- return X86II::MO_PIC_BASE_OFFSET;
-
- // Direct static reference to label.
- return X86II::MO_NO_FLAG;
+unsigned char X86Subtarget::classifyBlockAddressReference() const {
+ return classifyLocalReference(nullptr);
}
/// Classify a global variable reference for the current subtarget according to
/// how we should reference it in a non-pcrel context.
-unsigned char X86Subtarget::
-ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const {
- // DLLImport only exists on windows, it is implemented as a load from a
- // DLLIMPORT stub.
- if (GV->hasDLLImportStorageClass())
- return X86II::MO_DLLIMPORT;
+unsigned char
+X86Subtarget::classifyGlobalReference(const GlobalValue *GV) const {
+ return classifyGlobalReference(GV, *GV->getParent());
+}
- bool isDef = GV->isStrongDefinitionForLinker();
+unsigned char
+X86Subtarget::classifyLocalReference(const GlobalValue *GV) const {
+ // 64 bits can use %rip addressing for anything local.
+ if (is64Bit())
+ return X86II::MO_NO_FLAG;
- // X86-64 in PIC mode.
- if (isPICStyleRIPRel()) {
- // Large model never uses stubs.
- if (TM.getCodeModel() == CodeModel::Large)
- return X86II::MO_NO_FLAG;
+ // If this is for a position dependent executable, the static linker can
+ // figure it out.
+ if (!isPositionIndependent())
+ return X86II::MO_NO_FLAG;
- if (isTargetDarwin()) {
- // If symbol visibility is hidden, the extra load is not needed if
- // target is x86-64 or the symbol is definitely defined in the current
- // translation unit.
- if (GV->hasDefaultVisibility() && !isDef)
- return X86II::MO_GOTPCREL;
- } else if (!isTargetWin64()) {
- assert(isTargetELF() && "Unknown rip-relative target");
+ // The COFF dynamic linker just patches the executable sections.
+ if (isTargetCOFF())
+ return X86II::MO_NO_FLAG;
- // Extra load is needed for all externally visible.
- if (!GV->hasLocalLinkage() && GV->hasDefaultVisibility())
- return X86II::MO_GOTPCREL;
- }
+ if (isTargetDarwin()) {
+ // 32 bit macho has no relocation for a-b if a is undefined, even if
+ // b is in the section that is being relocated.
+ // This means we have to use o load even for GVs that are known to be
+ // local to the dso.
+ if (GV && (GV->isDeclarationForLinker() || GV->hasCommonLinkage()))
+ return X86II::MO_DARWIN_NONLAZY_PIC_BASE;
- return X86II::MO_NO_FLAG;
+ return X86II::MO_PIC_BASE_OFFSET;
}
- if (isPICStyleGOT()) { // 32-bit ELF targets.
- // Extra load is needed for all externally visible.
- if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
- return X86II::MO_GOTOFF;
- return X86II::MO_GOT;
- }
+ return X86II::MO_GOTOFF;
+}
- if (isPICStyleStubPIC()) { // Darwin/32 in PIC mode.
- // Determine whether we have a stub reference and/or whether the reference
- // is relative to the PIC base or not.
+unsigned char X86Subtarget::classifyGlobalReference(const GlobalValue *GV,
+ const Module &M) const {
+ // Large model never uses stubs.
+ if (TM.getCodeModel() == CodeModel::Large)
+ return X86II::MO_NO_FLAG;
- // If this is a strong reference to a definition, it is definitely not
- // through a stub.
- if (isDef)
- return X86II::MO_PIC_BASE_OFFSET;
+ if (TM.shouldAssumeDSOLocal(M, GV))
+ return classifyLocalReference(GV);
- // Unless we have a symbol with hidden visibility, we have to go through a
- // normal $non_lazy_ptr stub because this symbol might be resolved late.
- if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference.
- return X86II::MO_DARWIN_NONLAZY_PIC_BASE;
+ if (isTargetCOFF())
+ return X86II::MO_DLLIMPORT;
- // If symbol visibility is hidden, we have a stub for common symbol
- // references and external declarations.
- if (GV->isDeclarationForLinker() || GV->hasCommonLinkage()) {
- // Hidden $non_lazy_ptr reference.
- return X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE;
- }
+ if (is64Bit())
+ return X86II::MO_GOTPCREL;
- // Otherwise, no stub.
- return X86II::MO_PIC_BASE_OFFSET;
+ if (isTargetDarwin()) {
+ if (!isPositionIndependent())
+ return X86II::MO_DARWIN_NONLAZY;
+ return X86II::MO_DARWIN_NONLAZY_PIC_BASE;
}
- if (isPICStyleStubNoDynamic()) { // Darwin/32 in -mdynamic-no-pic mode.
- // Determine whether we have a stub reference.
+ return X86II::MO_GOT;
+}
- // If this is a strong reference to a definition, it is definitely not
- // through a stub.
- if (isDef)
- return X86II::MO_NO_FLAG;
+unsigned char
+X86Subtarget::classifyGlobalFunctionReference(const GlobalValue *GV) const {
+ return classifyGlobalFunctionReference(GV, *GV->getParent());
+}
- // Unless we have a symbol with hidden visibility, we have to go through a
- // normal $non_lazy_ptr stub because this symbol might be resolved late.
- if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference.
- return X86II::MO_DARWIN_NONLAZY;
+unsigned char
+X86Subtarget::classifyGlobalFunctionReference(const GlobalValue *GV,
+ const Module &M) const {
+ if (TM.shouldAssumeDSOLocal(M, GV))
+ return X86II::MO_NO_FLAG;
+
+ assert(!isTargetCOFF());
- // Otherwise, no stub.
+ if (isTargetELF())
+ return X86II::MO_PLT;
+
+ if (is64Bit()) {
+ auto *F = dyn_cast_or_null<Function>(GV);
+ if (F && F->hasFnAttribute(Attribute::NonLazyBind))
+ // If the function is marked as non-lazy, generate an indirect call
+ // which loads from the GOT directly. This avoids runtime overhead
+ // at the cost of eager binding (and one extra byte of encoding).
+ return X86II::MO_GOTPCREL;
return X86II::MO_NO_FLAG;
}
- // Direct static reference to global.
return X86II::MO_NO_FLAG;
}
-
/// This function returns the name of a function which has an interface like
/// the non-standard bzero function, if such a function exists on the
/// current subtarget and it is considered preferable over memset with zero
@@ -165,7 +159,7 @@ bool X86Subtarget::hasSinCos() const {
}
/// Return true if the subtarget allows calls to immediate address.
-bool X86Subtarget::IsLegalToCallImmediateAddr(const TargetMachine &TM) const {
+bool X86Subtarget::isLegalToCallImmediateAddr() const {
// FIXME: I386 PE/COFF supports PC relative calls using IMAGE_REL_I386_REL32
// but WinCOFFObjectWriter::RecordRelocation cannot emit them. Once it does,
// the following check for Win32 should be removed.
@@ -227,18 +221,19 @@ void X86Subtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
assert((!In64BitMode || HasX86_64) &&
"64-bit code requested on a subtarget that doesn't support it!");
- // Stack alignment is 16 bytes on Darwin, Linux and Solaris (both
+ // Stack alignment is 16 bytes on Darwin, Linux, kFreeBSD and Solaris (both
// 32 and 64 bit) and for all 64-bit targets.
if (StackAlignOverride)
stackAlignment = StackAlignOverride;
else if (isTargetDarwin() || isTargetLinux() || isTargetSolaris() ||
- In64BitMode)
+ isTargetKFreeBSD() || In64BitMode)
stackAlignment = 16;
}
void X86Subtarget::initializeEnvironment() {
X86SSELevel = NoSSE;
X863DNowLevel = NoThreeDNow;
+ HasX87 = false;
HasCMov = false;
HasX86_64 = false;
HasPOPCNT = false;
@@ -261,6 +256,8 @@ void X86Subtarget::initializeEnvironment() {
HasLZCNT = false;
HasBMI = false;
HasBMI2 = false;
+ HasVBMI = false;
+ HasIFMA = false;
HasRTM = false;
HasHLE = false;
HasERI = false;
@@ -275,6 +272,7 @@ void X86Subtarget::initializeEnvironment() {
HasPRFCHW = false;
HasRDSEED = false;
HasLAHFSAHF = false;
+ HasMWAITX = false;
HasMPX = false;
IsBTMemSlow = false;
IsSHLDSlow = false;
@@ -283,6 +281,7 @@ void X86Subtarget::initializeEnvironment() {
HasSSEUnalignedMem = false;
HasCmpxchg16b = false;
UseLeaForSP = false;
+ HasFastPartialYMMWrite = false;
HasSlowDivide32 = false;
HasSlowDivide64 = false;
PadShortFunctions = false;
@@ -303,11 +302,11 @@ X86Subtarget &X86Subtarget::initializeSubtargetDependencies(StringRef CPU,
return *this;
}
-X86Subtarget::X86Subtarget(const Triple &TT, const std::string &CPU,
- const std::string &FS, const X86TargetMachine &TM,
+X86Subtarget::X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS,
+ const X86TargetMachine &TM,
unsigned StackAlignOverride)
: X86GenSubtargetInfo(TT, CPU, FS), X86ProcFamily(Others),
- PICStyle(PICStyles::None), TargetTriple(TT),
+ PICStyle(PICStyles::None), TM(TM), TargetTriple(TT),
StackAlignOverride(StackAlignOverride),
In64BitMode(TargetTriple.getArch() == Triple::x86_64),
In32BitMode(TargetTriple.getArch() == Triple::x86 &&
@@ -317,24 +316,16 @@ X86Subtarget::X86Subtarget(const Triple &TT, const std::string &CPU,
TSInfo(), InstrInfo(initializeSubtargetDependencies(CPU, FS)),
TLInfo(TM, *this), FrameLowering(*this, getStackAlignment()) {
// Determine the PICStyle based on the target selected.
- if (TM.getRelocationModel() == Reloc::Static) {
- // Unless we're in PIC or DynamicNoPIC mode, set the PIC style to None.
+ if (!isPositionIndependent())
setPICStyle(PICStyles::None);
- } else if (is64Bit()) {
- // PIC in 64 bit mode is always rip-rel.
+ else if (is64Bit())
setPICStyle(PICStyles::RIPRel);
- } else if (isTargetCOFF()) {
+ else if (isTargetCOFF())
setPICStyle(PICStyles::None);
- } else if (isTargetDarwin()) {
- if (TM.getRelocationModel() == Reloc::PIC_)
- setPICStyle(PICStyles::StubPIC);
- else {
- assert(TM.getRelocationModel() == Reloc::DynamicNoPIC);
- setPICStyle(PICStyles::StubDynamicNoPIC);
- }
- } else if (isTargetELF()) {
+ else if (isTargetDarwin())
+ setPICStyle(PICStyles::StubPIC);
+ else if (isTargetELF())
setPICStyle(PICStyles::GOT);
- }
}
bool X86Subtarget::enableEarlyIfConversion() const {