summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/X86/X86FastISel.cpp18
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp44
-rw-r--r--llvm/lib/Target/X86/X86Subtarget.cpp210
-rw-r--r--llvm/lib/Target/X86/X86Subtarget.h13
4 files changed, 130 insertions, 155 deletions
diff --git a/llvm/lib/Target/X86/X86FastISel.cpp b/llvm/lib/Target/X86/X86FastISel.cpp
index 69fd8bac64b..b5a000de631 100644
--- a/llvm/lib/Target/X86/X86FastISel.cpp
+++ b/llvm/lib/Target/X86/X86FastISel.cpp
@@ -947,10 +947,8 @@ bool X86FastISel::X86SelectCallAddress(const Value *V, X86AddressMode &AM) {
// base and index registers are unused.
assert(AM.Base.Reg == 0 && AM.IndexReg == 0);
AM.Base.Reg = X86::RIP;
- } else if (Subtarget->isPICStyleStubPIC()) {
- AM.GVOpFlags = X86II::MO_PIC_BASE_OFFSET;
- } else if (Subtarget->isPICStyleGOT()) {
- AM.GVOpFlags = X86II::MO_GOTOFF;
+ } else {
+ AM.GVOpFlags = Subtarget->classifyLocalReference(nullptr);
}
return true;
@@ -3453,17 +3451,13 @@ unsigned X86FastISel::X86MaterializeFP(const ConstantFP *CFP, MVT VT) {
// x86-32 PIC requires a PIC base register for constant pools.
unsigned PICBase = 0;
- unsigned char OpFlag = 0;
- if (Subtarget->isPICStyleStubPIC()) { // Not dynamic-no-pic
- OpFlag = X86II::MO_PIC_BASE_OFFSET;
+ unsigned char OpFlag = Subtarget->classifyLocalReference(nullptr);
+ if (OpFlag == X86II::MO_PIC_BASE_OFFSET)
PICBase = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
- } else if (Subtarget->isPICStyleGOT()) {
- OpFlag = X86II::MO_GOTOFF;
+ else if (OpFlag == X86II::MO_GOTOFF)
PICBase = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
- } else if (Subtarget->isPICStyleRIPRel() &&
- TM.getCodeModel() == CodeModel::Small) {
+ else if (Subtarget->is64Bit() && TM.getCodeModel() == CodeModel::Small)
PICBase = X86::RIP;
- }
// Create the load from the constant pool.
unsigned CPI = MCP.getConstantPoolIndex(CFP, Align);
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index b8c1d0dd4b8..6e4fbc18105 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -3279,21 +3279,9 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
}
}
} else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
- unsigned char OpFlags = 0;
-
- // On ELF targets, in either X86-64 or X86-32 mode, direct calls to
- // external symbols should go through the PLT.
- if (Subtarget.isTargetELF() &&
- DAG.getTarget().getRelocationModel() == Reloc::PIC_) {
- OpFlags = X86II::MO_PLT;
- } else if (Subtarget.isPICStyleStubAny() &&
- (!Subtarget.getTargetTriple().isMacOSX() ||
- Subtarget.getTargetTriple().isMacOSXVersionLT(10, 5))) {
- // PC-relative references to external symbols should go through $stub,
- // unless we're building with the leopard linker or later, which
- // automatically synthesizes these stubs.
- OpFlags = X86II::MO_DARWIN_STUB;
- }
+ const Module *Mod = DAG.getMachineFunction().getFunction()->getParent();
+ unsigned char OpFlags =
+ Subtarget.classifyGlobalFunctionReference(nullptr, *Mod);
Callee = DAG.getTargetExternalSymbol(
S->getSymbol(), getPointerTy(DAG.getDataLayout()), OpFlags);
@@ -12542,17 +12530,13 @@ X86TargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const {
// In PIC mode (unless we're in RIPRel PIC mode) we add an offset to the
// global base reg.
- unsigned char OpFlag = 0;
+ unsigned char OpFlag = Subtarget.classifyLocalReference(nullptr);
unsigned WrapperKind = X86ISD::Wrapper;
CodeModel::Model M = DAG.getTarget().getCodeModel();
if (Subtarget.isPICStyleRIPRel() &&
(M == CodeModel::Small || M == CodeModel::Kernel))
WrapperKind = X86ISD::WrapperRIP;
- else if (Subtarget.isPICStyleGOT())
- OpFlag = X86II::MO_GOTOFF;
- else if (Subtarget.isPICStyleStubPIC())
- OpFlag = X86II::MO_PIC_BASE_OFFSET;
auto PtrVT = getPointerTy(DAG.getDataLayout());
SDValue Result = DAG.getTargetConstantPool(
@@ -12574,17 +12558,13 @@ SDValue X86TargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {
// In PIC mode (unless we're in RIPRel PIC mode) we add an offset to the
// global base reg.
- unsigned char OpFlag = 0;
+ unsigned char OpFlag = Subtarget.classifyLocalReference(nullptr);
unsigned WrapperKind = X86ISD::Wrapper;
CodeModel::Model M = DAG.getTarget().getCodeModel();
if (Subtarget.isPICStyleRIPRel() &&
(M == CodeModel::Small || M == CodeModel::Kernel))
WrapperKind = X86ISD::WrapperRIP;
- else if (Subtarget.isPICStyleGOT())
- OpFlag = X86II::MO_GOTOFF;
- else if (Subtarget.isPICStyleStubPIC())
- OpFlag = X86II::MO_PIC_BASE_OFFSET;
auto PtrVT = getPointerTy(DAG.getDataLayout());
SDValue Result = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, OpFlag);
@@ -12606,22 +12586,14 @@ X86TargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const {
// In PIC mode (unless we're in RIPRel PIC mode) we add an offset to the
// global base reg.
- unsigned char OpFlag = 0;
+ const Module *Mod = DAG.getMachineFunction().getFunction()->getParent();
+ unsigned char OpFlag = Subtarget.classifyGlobalReference(nullptr, *Mod);
unsigned WrapperKind = X86ISD::Wrapper;
CodeModel::Model M = DAG.getTarget().getCodeModel();
if (Subtarget.isPICStyleRIPRel() &&
- (M == CodeModel::Small || M == CodeModel::Kernel)) {
- if (Subtarget.isTargetDarwin() || Subtarget.isTargetELF())
- OpFlag = X86II::MO_GOTPCREL;
+ (M == CodeModel::Small || M == CodeModel::Kernel))
WrapperKind = X86ISD::WrapperRIP;
- } else if (Subtarget.isPICStyleGOT()) {
- OpFlag = X86II::MO_GOT;
- } else if (Subtarget.isPICStyleStubPIC()) {
- OpFlag = X86II::MO_DARWIN_NONLAZY_PIC_BASE;
- } else if (Subtarget.isPICStyleStubNoDynamic()) {
- OpFlag = X86II::MO_DARWIN_NONLAZY;
- }
auto PtrVT = getPointerTy(DAG.getDataLayout());
SDValue Result = DAG.getTargetExternalSymbol(Sym, PtrVT, OpFlag);
diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp
index fe3cd466d00..7f033bea962 100644
--- a/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -47,136 +47,146 @@ 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;
+ return classifyLocalReference(nullptr);
+}
- if (isPICStyleStubPIC()) // Darwin/32 in PIC mode.
- return X86II::MO_PIC_BASE_OFFSET;
+// FIXME: make this a proper option
+static bool CanUseCopyRelocWithPIE = false;
- // Direct static reference to label.
- return X86II::MO_NO_FLAG;
-}
+static bool shouldAssumeDSOLocal(Reloc::Model RM, const Triple &TT,
+ const Module &M, const GlobalValue *GV) {
+ // DLLImport explicitly marks the GV as external.
+ if (GV && GV->hasDLLImportStorageClass())
+ return false;
-/// 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 {
- // DLLImport only exists on windows, it is implemented as a load from a
- // DLLIMPORT stub.
- if (GV->hasDLLImportStorageClass())
- return X86II::MO_DLLIMPORT;
+ // Every other GV is local on COFF
+ if (TT.isOSBinFormatCOFF())
+ return true;
+
+ if (RM == Reloc::Static)
+ return true;
+
+ if (GV && (GV->hasInternalLinkage() || !GV->hasDefaultVisibility()))
+ return true;
+
+ if (TT.isOSBinFormatELF()) {
+ assert(RM != Reloc::DynamicNoPIC);
+ // Some linkers can use copy relocations with pie executables.
+ if (M.getPIELevel() != PIELevel::Default) {
+ if (CanUseCopyRelocWithPIE)
+ return true;
- bool isDef = GV->isStrongDefinitionForLinker();
-
- // X86-64 in PIC mode.
- if (isPICStyleRIPRel()) {
- // Large model never uses stubs.
- if (TM.getCodeModel() == CodeModel::Large)
- 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");
-
- // Extra load is needed for all externally visible globals except with
- // PIE as the definition of the global in an executable is not
- // overridden.
-
- if (!GV->hasLocalLinkage() && GV->hasDefaultVisibility() &&
- !isGlobalDefinedInPIE(GV))
- return X86II::MO_GOTPCREL;
+ // If the symbol is defined, it cannot be preempted.
+ if (GV && !GV->isDeclarationForLinker())
+ return true;
+ return false;
}
- return X86II::MO_NO_FLAG;
+ // ELF supports preemption of other symbols.
+ return false;
}
- if (isPICStyleGOT()) { // 32-bit ELF targets.
- // Extra load is needed for all externally visible globals except with
- // PIE as the definition of the global in an executable is not overridden.
+ assert(TT.isOSBinFormatMachO());
+ if (GV && GV->isStrongDefinitionForLinker())
+ return true;
- if (GV->hasLocalLinkage() || GV->hasHiddenVisibility() ||
- isGlobalDefinedInPIE(GV))
- return X86II::MO_GOTOFF;
- return X86II::MO_GOT;
- }
+ return false;
+}
- 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.
+/// 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 {
+ return classifyGlobalReference(GV, *GV->getParent());
+}
- // If this is a strong reference to a definition, it is definitely not
- // through a stub.
- if (isDef)
- return X86II::MO_PIC_BASE_OFFSET;
+unsigned char
+X86Subtarget::classifyLocalReference(const GlobalValue *GV) const {
+ // 64 bits can use %rip addressing for anything local.
+ if (is64Bit())
+ return X86II::MO_NO_FLAG;
- // 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_lazy_ptr reference.
- return X86II::MO_DARWIN_NONLAZY_PIC_BASE;
+ // If this is for a position dependent executable, the static linker can
+ // figure it out.
+ if (TM.getRelocationModel() != Reloc::PIC_)
+ return X86II::MO_NO_FLAG;
- // If symbol visibility is hidden, we have a stub for common symbol
- // references and external declarations.
- if (GV->isDeclarationForLinker() || GV->hasCommonLinkage()) {
- // $non_lazy_ptr reference.
+ // The COFF dynamic linker just patches the executable sections.
+ if (isTargetCOFF())
+ return X86II::MO_NO_FLAG;
+
+ 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;
- }
- // Otherwise, no stub.
return X86II::MO_PIC_BASE_OFFSET;
}
- if (isPICStyleStubNoDynamic()) { // Darwin/32 in -mdynamic-no-pic mode.
- // Determine whether we have a stub reference.
+ return X86II::MO_GOTOFF;
+}
- // 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::classifyGlobalReference(const GlobalValue *GV,
+ const Module &M) const {
+ // Large model never uses stubs.
+ if (TM.getCodeModel() == CodeModel::Large)
+ return X86II::MO_NO_FLAG;
- // 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;
+ Reloc::Model RM = TM.getRelocationModel();
+ if (shouldAssumeDSOLocal(RM, TargetTriple, M, GV))
+ return classifyLocalReference(GV);
- // Otherwise, no stub.
- return X86II::MO_NO_FLAG;
+ if (isTargetCOFF())
+ return X86II::MO_DLLIMPORT;
+
+ if (is64Bit())
+ return X86II::MO_GOTPCREL;
+
+ if (isTargetDarwin()) {
+ if (RM != Reloc::PIC_)
+ return X86II::MO_DARWIN_NONLAZY;
+ return X86II::MO_DARWIN_NONLAZY_PIC_BASE;
}
- // Direct static reference to global.
- return X86II::MO_NO_FLAG;
+ return X86II::MO_GOT;
}
unsigned char
X86Subtarget::classifyGlobalFunctionReference(const GlobalValue *GV) const {
- // On ELF targets, in both X86-64 and X86-32 mode, direct calls to
- // external symbols most go through the PLT in PIC mode. If the symbol
- // has hidden or protected visibility, or if it is static or local, then
- // we don't need to use the PLT - we can directly call it.
- // In PIE mode, calls to global functions don't need to go through PLT
- if (isTargetELF() && TM.getRelocationModel() == Reloc::PIC_ &&
- !isGlobalDefinedInPIE(GV) && GV->hasDefaultVisibility() &&
- !GV->hasLocalLinkage()) {
+ return classifyGlobalFunctionReference(GV, *GV->getParent());
+}
+
+unsigned char
+X86Subtarget::classifyGlobalFunctionReference(const GlobalValue *GV,
+ const Module &M) const {
+ if (shouldAssumeDSOLocal(TM.getRelocationModel(), TargetTriple, M, GV))
+ return X86II::MO_NO_FLAG;
+
+ assert(!isTargetCOFF());
+
+ if (isTargetELF())
return X86II::MO_PLT;
- } else if (isPICStyleStubAny() && !GV->isStrongDefinitionForLinker() &&
- (!getTargetTriple().isMacOSX() ||
- getTargetTriple().isMacOSXVersionLT(10, 5))) {
- // PC-relative references to external symbols should go through $stub,
- // unless we're building with the leopard linker or later, which
- // automatically synthesizes these stubs.
- return X86II::MO_DARWIN_STUB;
- } else if (isPICStyleRIPRel() && isa<Function>(GV) &&
- cast<Function>(GV)->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;
+
+ 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;
}
+ // PC-relative references to external symbols should go through $stub,
+ // unless we're building with the leopard linker or later, which
+ // automatically synthesizes these stubs.
+ if (!getTargetTriple().isMacOSX() ||
+ getTargetTriple().isMacOSXVersionLT(10, 5))
+ return X86II::MO_DARWIN_STUB;
+
return X86II::MO_NO_FLAG;
}
diff --git a/llvm/lib/Target/X86/X86Subtarget.h b/llvm/lib/Target/X86/X86Subtarget.h
index 68672c28060..f77a33f2348 100644
--- a/llvm/lib/Target/X86/X86Subtarget.h
+++ b/llvm/lib/Target/X86/X86Subtarget.h
@@ -556,18 +556,17 @@ public:
}
}
- /// Determine if this global is defined in a Position Independent
- /// Executable (PIE) where its definition cannot be interposed.
- bool isGlobalDefinedInPIE(const GlobalValue *GV) const {
- return GV->getParent()->getPIELevel() != PIELevel::Default &&
- !GV->isDeclarationForLinker();
- }
-
/// Classify a global variable reference for the current subtarget according
/// to how we should reference it in a non-pcrel context.
+ unsigned char classifyLocalReference(const GlobalValue *GV) const;
+
+ unsigned char classifyGlobalReference(const GlobalValue *GV,
+ const Module &M) const;
unsigned char classifyGlobalReference(const GlobalValue *GV) const;
/// Classify a global function reference for the current subtarget.
+ unsigned char classifyGlobalFunctionReference(const GlobalValue *GV,
+ const Module &M) const;
unsigned char classifyGlobalFunctionReference(const GlobalValue *GV) const;
/// Classify a blockaddress reference for the current subtarget according to
OpenPOWER on IntegriCloud