summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/CodeGen/Analysis.cpp39
-rw-r--r--llvm/lib/Target/TargetMachine.cpp18
-rw-r--r--llvm/test/CodeGen/X86/tls.ll15
3 files changed, 42 insertions, 30 deletions
diff --git a/llvm/lib/CodeGen/Analysis.cpp b/llvm/lib/CodeGen/Analysis.cpp
index 73bd3d29eae..d3b3a9de110 100644
--- a/llvm/lib/CodeGen/Analysis.cpp
+++ b/llvm/lib/CodeGen/Analysis.cpp
@@ -651,33 +651,32 @@ bool llvm::shouldAssumeDSOLocal(Reloc::Model RM, const Triple &TT,
if (TT.isOSBinFormatCOFF())
return true;
- if (RM == Reloc::Static)
- return true;
-
if (GV && (GV->hasLocalLinkage() || !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;
+ if (TT.isOSBinFormatMachO()) {
+ if (RM == Reloc::Static)
+ return true;
+ return GV && GV->isStrongDefinitionForLinker();
+ }
- // If the symbol is defined, it cannot be preempted.
- if (GV && !GV->isDeclarationForLinker())
- return true;
- return false;
- }
+ assert(TT.isOSBinFormatELF());
+ assert(RM != Reloc::DynamicNoPIC);
- // ELF supports preemption of other symbols.
- return false;
- }
+ bool IsExecutable =
+ RM == Reloc::Static || M.getPIELevel() != PIELevel::Default;
+ if (IsExecutable) {
+ // If the symbol is defined, it cannot be preempted.
+ if (GV && !GV->isDeclarationForLinker())
+ return true;
- assert(TT.isOSBinFormatMachO());
- if (GV && GV->isStrongDefinitionForLinker())
- return true;
+ bool IsTLS = GV && GV->isThreadLocal();
+ // Check if we can use copy relocations.
+ if (!IsTLS && (RM == Reloc::Static || CanUseCopyRelocWithPIE))
+ return true;
+ }
+ // ELF supports preemption of other symbols.
return false;
}
diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp
index b62471597e0..220f1f3183d 100644
--- a/llvm/lib/Target/TargetMachine.cpp
+++ b/llvm/lib/Target/TargetMachine.cpp
@@ -13,6 +13,7 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
@@ -106,22 +107,19 @@ static TLSModel::Model getSelectedTLSModel(const GlobalValue *GV) {
}
TLSModel::Model TargetMachine::getTLSModel(const GlobalValue *GV) const {
- bool isLocal = GV->hasLocalLinkage();
- bool isDeclaration = GV->isDeclaration();
- bool isPIC = getRelocationModel() == Reloc::PIC_;
- bool isPIE = GV->getParent()->getPIELevel() != PIELevel::Default;
- // FIXME: what should we do for protected and internal visibility?
- // For variables, is internal different from hidden?
- bool isHidden = GV->hasHiddenVisibility();
+ bool IsPIE = GV->getParent()->getPIELevel() != PIELevel::Default;
+ Reloc::Model RM = getRelocationModel();
+ bool IsSharedLibrary = RM == Reloc::PIC_ && !IsPIE;
+ bool IsLocal = shouldAssumeDSOLocal(RM, TargetTriple, *GV->getParent(), GV);
TLSModel::Model Model;
- if (isPIC && !isPIE) {
- if (isLocal || isHidden)
+ if (IsSharedLibrary) {
+ if (IsLocal)
Model = TLSModel::LocalDynamic;
else
Model = TLSModel::GeneralDynamic;
} else {
- if (!isDeclaration || isHidden)
+ if (IsLocal)
Model = TLSModel::LocalExec;
else
Model = TLSModel::InitialExec;
diff --git a/llvm/test/CodeGen/X86/tls.ll b/llvm/test/CodeGen/X86/tls.ll
index 0f3d3adec4c..85c51e618b2 100644
--- a/llvm/test/CodeGen/X86/tls.ll
+++ b/llvm/test/CodeGen/X86/tls.ll
@@ -10,6 +10,7 @@
@i3 = internal thread_local global i32 15
@i4 = hidden thread_local global i32 15
@i5 = external hidden thread_local global i32
+@i6 = external protected thread_local global i32
@s1 = thread_local global i16 15
@b1 = thread_local global i8 0
@b2 = thread_local(localexec) global i8 0
@@ -438,3 +439,17 @@ entry:
ret i8* @b2
}
+
+define i32* @f16() {
+; X32_LINUX-LABEL: f16:
+; X32_LINUX: movl %gs:0, %eax
+; X32_LINUX-NEXT: leal i6@NTPOFF(%eax), %eax
+; X32_LINUX-NEXT: ret
+
+; X64_LINUX-LABEL: f16:
+; X64_LINUX: movq %fs:0, %rax
+; X64_LINUX-NEXT: leaq i6@TPOFF(%rax), %rax
+; X64_LINUX-NEXT: ret
+
+ ret i32* @i6
+}
OpenPOWER on IntegriCloud