diff options
-rw-r--r-- | docs/LangRef.rst | 51 | ||||
-rw-r--r-- | include/llvm/IR/GlobalValue.h | 33 | ||||
-rw-r--r-- | include/llvm/IR/GlobalVariable.h | 21 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.cpp | 48 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.h | 6 | ||||
-rw-r--r-- | lib/Bitcode/Reader/BitcodeReader.cpp | 2 | ||||
-rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 9 | ||||
-rw-r--r-- | lib/IR/AsmWriter.cpp | 1 | ||||
-rw-r--r-- | lib/IR/Globals.cpp | 6 | ||||
-rw-r--r-- | lib/Target/AArch64/AArch64FastISel.cpp | 12 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCFastISel.cpp | 8 | ||||
-rw-r--r-- | lib/Target/TargetMachine.cpp | 15 | ||||
-rw-r--r-- | lib/Target/X86/X86FastISel.cpp | 13 | ||||
-rw-r--r-- | test/CodeGen/Mips/tls-alias.ll | 2 | ||||
-rw-r--r-- | test/CodeGen/X86/2008-03-12-ThreadLocalAlias.ll | 2 | ||||
-rw-r--r-- | test/CodeGen/X86/aliases.ll | 18 | ||||
-rw-r--r-- | test/Feature/alias2.ll | 3 |
18 files changed, 143 insertions, 111 deletions
diff --git a/docs/LangRef.rst b/docs/LangRef.rst index fa40363a75..650012e7f9 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -464,6 +464,34 @@ DLL storage class: exists for defining a dll interface, the compiler, assembler and linker know it is externally referenced and must refrain from deleting the symbol. +.. _tls_model: + +Thread Local Storage Models +--------------------------- + +A variable may be defined as ``thread_local``, which means that it will +not be shared by threads (each thread will have a separated copy of the +variable). Not all targets support thread-local variables. Optionally, a +TLS model may be specified: + +``localdynamic`` + For variables that are only used within the current shared library. +``initialexec`` + For variables in modules that will not be loaded dynamically. +``localexec`` + For variables defined in the executable and only used within it. + +If no explicit model is given, the "general dynamic" model is used. + +The models correspond to the ELF TLS models; see `ELF Handling For +Thread-Local Storage <http://people.redhat.com/drepper/tls.pdf>`_ for +more information on under which circumstances the different models may +be used. The target may choose a different TLS model if the specified +model is not supported, or if a better choice of model can be made. + +A model can also be specified in a alias, but then it only governs how +the alias is accessed. It will not have any effect in the aliasee. + .. _namedtypes: Structure Types @@ -497,24 +525,6 @@ to be placed in, and may have an optional explicit alignment specified. Global variables in other translation units can also be declared, in which case they don't have an initializer. -A variable may be defined as ``thread_local``, which means that it will -not be shared by threads (each thread will have a separated copy of the -variable). Not all targets support thread-local variables. Optionally, a -TLS model may be specified: - -``localdynamic`` - For variables that are only used within the current shared library. -``initialexec`` - For variables in modules that will not be loaded dynamically. -``localexec`` - For variables defined in the executable and only used within it. - -The models correspond to the ELF TLS models; see `ELF Handling For -Thread-Local Storage <http://people.redhat.com/drepper/tls.pdf>`_ for -more information on under which circumstances the different models may -be used. The target may choose a different TLS model if the specified -model is not supported, or if a better choice of model can be made. - A variable may be defined as a global ``constant``, which indicates that the contents of the variable will **never** be modified (enabling better optimization, allowing the global data to be placed in the read-only @@ -572,6 +582,9 @@ iteration. Globals can also have a :ref:`DLL storage class <dllstorageclass>`. +Variables and aliasaes can have a +:ref:`Thread Local Storage Model <tls_model>`. + Syntax:: [@<GlobalVarName> =] [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal] @@ -674,7 +687,7 @@ Aliases may have an optional :ref:`linkage type <linkage>`, an optional Syntax:: - @<Name> = [Visibility] [DLLStorageClass] alias [Linkage] <AliaseeTy> @<Aliasee> + @<Name> = [Visibility] [DLLStorageClass] [ThreadLocal] alias [Linkage] <AliaseeTy> @<Aliasee> The linkage must be one of ``private``, ``internal``, ``linkonce``, ``weak``, ``linkonce_odr``, ``weak_odr``, ``external``. Note that some system linkers diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 10df372945..04c97a01d6 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -63,7 +63,8 @@ protected: LinkageTypes Linkage, const Twine &Name) : Constant(Ty, VTy, Ops, NumOps), Linkage(Linkage), Visibility(DefaultVisibility), UnnamedAddr(0), - DllStorageClass(DefaultStorageClass), Parent(nullptr) { + DllStorageClass(DefaultStorageClass), + ThreadLocal(NotThreadLocal), Parent(nullptr) { setName(Name); } @@ -74,21 +75,32 @@ protected: unsigned UnnamedAddr : 1; // This value's address is not significant unsigned DllStorageClass : 2; // DLL storage class + unsigned ThreadLocal : 3; // Is this symbol "Thread Local", if so, what is + // the desired model? + private: // Give subclasses access to what otherwise would be wasted padding. - // (22 + 2 + 1 + 2 + 5) == 32. - unsigned SubClassData : 22; + // (19 + 3 + 2 + 1 + 2 + 5) == 32. + unsigned SubClassData : 19; protected: unsigned getGlobalValueSubClassData() const { return SubClassData; } void setGlobalValueSubClassData(unsigned V) { - assert(V < (1 << 22) && "It will not fit"); + assert(V < (1 << 19) && "It will not fit"); SubClassData = V; } Module *Parent; // The containing module. public: + enum ThreadLocalMode { + NotThreadLocal = 0, + GeneralDynamicTLSModel, + LocalDynamicTLSModel, + InitialExecTLSModel, + LocalExecTLSModel + }; + ~GlobalValue() { removeDeadConstantUsers(); // remove any dead constants using this. } @@ -110,6 +122,19 @@ public: Visibility = V; } + /// If the value is "Thread Local", its value isn't shared by the threads. + bool isThreadLocal() const { return getThreadLocalMode() != NotThreadLocal; } + void setThreadLocal(bool Val) { + setThreadLocalMode(Val ? GeneralDynamicTLSModel : NotThreadLocal); + } + void setThreadLocalMode(ThreadLocalMode Val) { + assert(Val == NotThreadLocal || getValueID() != Value::FunctionVal); + ThreadLocal = Val; + } + ThreadLocalMode getThreadLocalMode() const { + return static_cast<ThreadLocalMode>(ThreadLocal); + } + DLLStorageClassTypes getDLLStorageClass() const { return DLLStorageClassTypes(DllStorageClass); } diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 8cd4332b1a..4189ccb90a 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -41,9 +41,6 @@ class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> { void setParent(Module *parent); bool isConstantGlobal : 1; // Is this a global constant? - unsigned threadLocalMode : 3; // Is this symbol "Thread Local", - // if so, what is the desired - // model? bool isExternallyInitializedConstant : 1; // Is this a global whose value // can change from its initial // value before global @@ -55,14 +52,6 @@ public: return User::operator new(s, 1); } - enum ThreadLocalMode { - NotThreadLocal = 0, - GeneralDynamicTLSModel, - LocalDynamicTLSModel, - InitialExecTLSModel, - LocalExecTLSModel - }; - /// GlobalVariable ctor - If a parent module is specified, the global is /// automatically inserted into the end of the specified modules global list. GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage, @@ -155,16 +144,6 @@ public: bool isConstant() const { return isConstantGlobal; } void setConstant(bool Val) { isConstantGlobal = Val; } - /// If the value is "Thread Local", its value isn't shared by the threads. - bool isThreadLocal() const { return threadLocalMode != NotThreadLocal; } - void setThreadLocal(bool Val) { - threadLocalMode = Val ? GeneralDynamicTLSModel : NotThreadLocal; - } - void setThreadLocalMode(ThreadLocalMode Val) { threadLocalMode = Val; } - ThreadLocalMode getThreadLocalMode() const { - return static_cast<ThreadLocalMode>(threadLocalMode); - } - bool isExternallyInitialized() const { return isExternallyInitializedConstant; } diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 3282e8a23b..f0efa9414d 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -259,10 +259,13 @@ bool LLParser::ParseTopLevelEntities() { case lltok::kw_extern_weak: // OptionalLinkage case lltok::kw_external: { // OptionalLinkage unsigned Linkage, Visibility, DLLStorageClass; + GlobalVariable::ThreadLocalMode TLM; if (ParseOptionalLinkage(Linkage) || ParseOptionalVisibility(Visibility) || ParseOptionalDLLStorageClass(DLLStorageClass) || - ParseGlobal("", SMLoc(), Linkage, true, Visibility, DLLStorageClass)) + ParseOptionalThreadLocal(TLM) || + ParseGlobal("", SMLoc(), Linkage, true, Visibility, DLLStorageClass, + TLM)) return true; break; } @@ -270,18 +273,28 @@ bool LLParser::ParseTopLevelEntities() { case lltok::kw_hidden: // OptionalVisibility case lltok::kw_protected: { // OptionalVisibility unsigned Visibility, DLLStorageClass; + GlobalVariable::ThreadLocalMode TLM; if (ParseOptionalVisibility(Visibility) || ParseOptionalDLLStorageClass(DLLStorageClass) || - ParseGlobal("", SMLoc(), 0, false, Visibility, DLLStorageClass)) + ParseOptionalThreadLocal(TLM) || + ParseGlobal("", SMLoc(), 0, false, Visibility, DLLStorageClass, TLM)) + return true; + break; + } + + case lltok::kw_thread_local: { // OptionalThreadLocal + GlobalVariable::ThreadLocalMode TLM; + if (ParseOptionalThreadLocal(TLM) || + ParseGlobal("", SMLoc(), 0, false, 0, 0, TLM)) return true; break; } - case lltok::kw_thread_local: // OptionalThreadLocal case lltok::kw_addrspace: // OptionalAddrSpace case lltok::kw_constant: // GlobalType case lltok::kw_global: // GlobalType - if (ParseGlobal("", SMLoc(), 0, false, 0, 0)) return true; + if (ParseGlobal("", SMLoc(), 0, false, 0, 0, GlobalValue::NotThreadLocal)) + return true; break; case lltok::kw_attributes: if (ParseUnnamedAttrGrp()) return true; break; @@ -470,15 +483,17 @@ bool LLParser::ParseUnnamedGlobal() { bool HasLinkage; unsigned Linkage, Visibility, DLLStorageClass; + GlobalVariable::ThreadLocalMode TLM; if (ParseOptionalLinkage(Linkage, HasLinkage) || ParseOptionalVisibility(Visibility) || - ParseOptionalDLLStorageClass(DLLStorageClass)) + ParseOptionalDLLStorageClass(DLLStorageClass) || + ParseOptionalThreadLocal(TLM)) return true; if (HasLinkage || Lex.getKind() != lltok::kw_alias) return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, - DLLStorageClass); - return ParseAlias(Name, NameLoc, Visibility, DLLStorageClass); + DLLStorageClass, TLM); + return ParseAlias(Name, NameLoc, Visibility, DLLStorageClass, TLM); } /// ParseNamedGlobal: @@ -493,16 +508,18 @@ bool LLParser::ParseNamedGlobal() { bool HasLinkage; unsigned Linkage, Visibility, DLLStorageClass; + GlobalVariable::ThreadLocalMode TLM; if (ParseToken(lltok::equal, "expected '=' in global variable") || ParseOptionalLinkage(Linkage, HasLinkage) || ParseOptionalVisibility(Visibility) || - ParseOptionalDLLStorageClass(DLLStorageClass)) + ParseOptionalDLLStorageClass(DLLStorageClass) || + ParseOptionalThreadLocal(TLM)) return true; if (HasLinkage || Lex.getKind() != lltok::kw_alias) return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, - DLLStorageClass); - return ParseAlias(Name, NameLoc, Visibility, DLLStorageClass); + DLLStorageClass, TLM); + return ParseAlias(Name, NameLoc, Visibility, DLLStorageClass, TLM); } // MDString: @@ -639,7 +656,8 @@ static bool isValidVisibilityForLinkage(unsigned V, unsigned L) { /// Everything through DLL storage class has already been parsed. /// bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, - unsigned Visibility, unsigned DLLStorageClass) { + unsigned Visibility, unsigned DLLStorageClass, + GlobalVariable::ThreadLocalMode TLM) { assert(Lex.getKind() == lltok::kw_alias); Lex.Lex(); LocTy LinkageLoc = Lex.getLoc(); @@ -699,6 +717,7 @@ bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, std::unique_ptr<GlobalAlias> GA( GlobalAlias::create(Ty, AddrSpace, (GlobalValue::LinkageTypes)Linkage, Name, Aliasee, /*Parent*/ nullptr)); + GA->setThreadLocalMode(TLM); GA->setVisibility((GlobalValue::VisibilityTypes)Visibility); GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); @@ -753,21 +772,20 @@ bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, /// bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, unsigned Linkage, bool HasLinkage, - unsigned Visibility, unsigned DLLStorageClass) { + unsigned Visibility, unsigned DLLStorageClass, + GlobalVariable::ThreadLocalMode TLM) { if (!isValidVisibilityForLinkage(Visibility, Linkage)) return Error(NameLoc, "symbol with local linkage must have default visibility"); unsigned AddrSpace; bool IsConstant, UnnamedAddr, IsExternallyInitialized; - GlobalVariable::ThreadLocalMode TLM; LocTy UnnamedAddrLoc; LocTy IsExternallyInitializedLoc; LocTy TyLoc; Type *Ty = nullptr; - if (ParseOptionalThreadLocal(TLM) || - ParseOptionalAddrSpace(AddrSpace) || + if (ParseOptionalAddrSpace(AddrSpace) || ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr, &UnnamedAddrLoc) || ParseOptionalToken(lltok::kw_externally_initialized, diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index e2bf46290b..1257b0aadc 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -239,9 +239,11 @@ namespace llvm { bool ParseNamedGlobal(); bool ParseGlobal(const std::string &Name, LocTy Loc, unsigned Linkage, bool HasLinkage, unsigned Visibility, - unsigned DLLStorageClass); + unsigned DLLStorageClass, + GlobalVariable::ThreadLocalMode TLM); bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Visibility, - unsigned DLLStorageClass); + unsigned DLLStorageClass, + GlobalVariable::ThreadLocalMode TLM); bool ParseStandaloneMetadata(); bool ParseNamedMetadata(); bool ParseMDString(MDString *&Result); diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 4170f98567..a8fd8fab50 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2017,6 +2017,8 @@ error_code BitcodeReader::ParseModule(bool Resume) { NewGA->setDLLStorageClass(GetDecodedDLLStorageClass(Record[4])); else UpgradeDLLImportExportLinkage(NewGA, Record[2]); + if (Record.size() > 5) + NewGA->setThreadLocalMode(GetDecodedThreadLocalMode(Record[5])); ValueList.push_back(NewGA); AliasInits.push_back(std::make_pair(NewGA, Record[1])); break; diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index cc73b842e3..dddcbc6f7e 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -511,7 +511,7 @@ static unsigned getEncodedDLLStorageClass(const GlobalValue &GV) { llvm_unreachable("Invalid DLL storage class"); } -static unsigned getEncodedThreadLocalMode(const GlobalVariable &GV) { +static unsigned getEncodedThreadLocalMode(const GlobalValue &GV) { switch (GV.getThreadLocalMode()) { case GlobalVariable::NotThreadLocal: return 0; case GlobalVariable::GeneralDynamicTLSModel: return 1; @@ -668,6 +668,8 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Vals.push_back(getEncodedLinkage(A)); Vals.push_back(getEncodedVisibility(A)); Vals.push_back(getEncodedDLLStorageClass(A)); + if (A.isThreadLocal()) + Vals.push_back(getEncodedThreadLocalMode(A)); unsigned AbbrevToUse = 0; Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse); Vals.clear(); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index b1b8035a7d..51ae11dea2 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1190,15 +1190,8 @@ SDValue SelectionDAG::getGlobalAddress(const GlobalValue *GV, SDLoc DL, if (BitWidth < 64) Offset = SignExtend64(Offset, BitWidth); - const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); - if (!GVar) { - // If GV is an alias then use the aliasee for determining thread-localness. - if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) - GVar = dyn_cast_or_null<GlobalVariable>(GA->getAliasee()); - } - unsigned Opc; - if (GVar && GVar->isThreadLocal()) + if (GV->isThreadLocal()) Opc = isTargetGA ? ISD::TargetGlobalTLSAddress : ISD::GlobalTLSAddress; else Opc = isTargetGA ? ISD::TargetGlobalAddress : ISD::GlobalAddress; diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 0fef0d0a18..8aee77ac07 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1488,6 +1488,7 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { } PrintVisibility(GA->getVisibility(), Out); PrintDLLStorageClass(GA->getDLLStorageClass(), Out); + PrintThreadLocalModel(GA->getThreadLocalMode(), Out); Out << "alias "; diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index c905cfe31e..344a08d8f3 100644 --- a/lib/IR/Globals.cpp +++ b/lib/IR/Globals.cpp @@ -113,8 +113,9 @@ GlobalVariable::GlobalVariable(Type *Ty, bool constant, LinkageTypes Link, : GlobalObject(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal, OperandTraits<GlobalVariable>::op_begin(this), InitVal != nullptr, Link, Name), - isConstantGlobal(constant), threadLocalMode(TLMode), + isConstantGlobal(constant), isExternallyInitializedConstant(isExternallyInitialized) { + setThreadLocalMode(TLMode); if (InitVal) { assert(InitVal->getType() == Ty && "Initializer should be the same type as the GlobalVariable!"); @@ -132,8 +133,9 @@ GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant, : GlobalObject(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal, OperandTraits<GlobalVariable>::op_begin(this), InitVal != nullptr, Link, Name), - isConstantGlobal(constant), threadLocalMode(TLMode), + isConstantGlobal(constant), isExternallyInitializedConstant(isExternallyInitialized) { + setThreadLocalMode(TLMode); if (InitVal) { assert(InitVal->getType() == Ty && "Initializer should be the same type as the GlobalVariable!"); diff --git a/lib/Target/AArch64/AArch64FastISel.cpp b/lib/Target/AArch64/AArch64FastISel.cpp index c3b53692fb..f97cfb943d 100644 --- a/lib/Target/AArch64/AArch64FastISel.cpp +++ b/lib/Target/AArch64/AArch64FastISel.cpp @@ -240,21 +240,15 @@ unsigned AArch64FastISel::AArch64MaterializeFP(const ConstantFP *CFP, MVT VT) { } unsigned AArch64FastISel::AArch64MaterializeGV(const GlobalValue *GV) { - // We can't handle thread-local variables quickly yet. Unfortunately we have - // to peer through any aliases to find out if that rule applies. - const GlobalValue *TLSGV = GV; - if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) - TLSGV = GA->getAliasee(); + // We can't handle thread-local variables quickly yet. + if (GV->isThreadLocal()) + return 0; // MachO still uses GOT for large code-model accesses, but ELF requires // movz/movk sequences, which FastISel doesn't handle yet. if (TM.getCodeModel() != CodeModel::Small && !Subtarget->isTargetMachO()) return 0; - if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(TLSGV)) - if (GVar->isThreadLocal()) - return 0; - unsigned char OpFlags = Subtarget->ClassifyGlobalReference(GV, TM); EVT DestEVT = TLI.getValueType(GV->getType(), true); diff --git a/lib/Target/PowerPC/PPCFastISel.cpp b/lib/Target/PowerPC/PPCFastISel.cpp index ed3cb4d329..f55984ea9d 100644 --- a/lib/Target/PowerPC/PPCFastISel.cpp +++ b/lib/Target/PowerPC/PPCFastISel.cpp @@ -1859,15 +1859,9 @@ unsigned PPCFastISel::PPCMaterializeGV(const GlobalValue *GV, MVT VT) { // handle switches; if that changes, we need them as well. For now, // what follows assumes everything's a generic (or TLS) global address. const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); - if (!GVar) { - // If GV is an alias, use the aliasee for determining thread-locality. - if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) - GVar = dyn_cast_or_null<GlobalVariable>(GA->getAliasee()); - } // FIXME: We don't yet handle the complexity of TLS. - bool IsTLS = GVar && GVar->isThreadLocal(); - if (IsTLS) + if (GV->isThreadLocal()) return 0; // For small code model, generate a simple TOC load. diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp index 8365f64dc5..95c8cb66f4 100644 --- a/lib/Target/TargetMachine.cpp +++ b/lib/Target/TargetMachine.cpp @@ -88,8 +88,8 @@ CodeModel::Model TargetMachine::getCodeModel() const { } /// Get the IR-specified TLS model for Var. -static TLSModel::Model getSelectedTLSModel(const GlobalVariable *Var) { - switch (Var->getThreadLocalMode()) { +static TLSModel::Model getSelectedTLSModel(const GlobalValue *GV) { + switch (GV->getThreadLocalMode()) { case GlobalVariable::NotThreadLocal: llvm_unreachable("getSelectedTLSModel for non-TLS variable"); break; @@ -127,13 +127,10 @@ TLSModel::Model TargetMachine::getTLSModel(const GlobalValue *GV) const { Model = TLSModel::InitialExec; } - const GlobalVariable *Var = dyn_cast<GlobalVariable>(GV); - if (Var) { - // If the user specified a more specific model, use that. - TLSModel::Model SelectedModel = getSelectedTLSModel(Var); - if (SelectedModel > Model) - return SelectedModel; - } + // If the user specified a more specific model, use that. + TLSModel::Model SelectedModel = getSelectedTLSModel(GV); + if (SelectedModel > Model) + return SelectedModel; return Model; } diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index 56bcfa30ff..2ef4bf29cc 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -355,17 +355,8 @@ bool X86FastISel::handleConstantAddresses(const Value *V, X86AddressMode &AM) { return false; // Can't handle TLS yet. - if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) - if (GVar->isThreadLocal()) - return false; - - // Can't handle TLS yet, part 2 (this is slightly crazy, but this is how - // it works...). - if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) - if (const GlobalVariable *GVar = - dyn_cast_or_null<GlobalVariable>(GA->getAliasee())) - if (GVar->isThreadLocal()) - return false; + if (GV->isThreadLocal()) + return false; // RIP-relative addresses can't have additional register operands, so if // we've already folded stuff into the addressing mode, just force the diff --git a/test/CodeGen/Mips/tls-alias.ll b/test/CodeGen/Mips/tls-alias.ll index 80fbe87a8d..b61f84e037 100644 --- a/test/CodeGen/Mips/tls-alias.ll +++ b/test/CodeGen/Mips/tls-alias.ll @@ -1,7 +1,7 @@ ; RUN: llc -march=mipsel -relocation-model=pic -disable-mips-delay-filler < %s | FileCheck %s @foo = thread_local global i32 42 -@bar = hidden alias i32* @foo +@bar = hidden thread_local alias i32* @foo define i32* @zed() { ; CHECK-DAG: __tls_get_addr diff --git a/test/CodeGen/X86/2008-03-12-ThreadLocalAlias.ll b/test/CodeGen/X86/2008-03-12-ThreadLocalAlias.ll index e64375a2b3..a0106d7798 100644 --- a/test/CodeGen/X86/2008-03-12-ThreadLocalAlias.ll +++ b/test/CodeGen/X86/2008-03-12-ThreadLocalAlias.ll @@ -8,7 +8,7 @@ target triple = "i386-pc-linux-gnu" @__resp = thread_local global %struct.__res_state* @_res ; <%struct.__res_state**> [#uses=1] @_res = global %struct.__res_state zeroinitializer, section ".bss" ; <%struct.__res_state*> [#uses=1] -@__libc_resp = hidden alias %struct.__res_state** @__resp ; <%struct.__res_state**> [#uses=2] +@__libc_resp = hidden thread_local alias %struct.__res_state** @__resp ; <%struct.__res_state**> [#uses=2] define i32 @foo() { ; CHECK-LABEL: foo: diff --git a/test/CodeGen/X86/aliases.ll b/test/CodeGen/X86/aliases.ll index 8487c6082b..d207880d66 100644 --- a/test/CodeGen/X86/aliases.ll +++ b/test/CodeGen/X86/aliases.ll @@ -1,4 +1,20 @@ -; RUN: llc < %s -mtriple=i686-pc-linux-gnu -asm-verbose=false | FileCheck %s +; RUN: llc < %s -mtriple=i686-pc-linux-gnu -asm-verbose=false \ +; RUN: -relocation-model=pic | FileCheck %s + +@thread_var = thread_local global i32 42, align 4 +@thread_alias = thread_local(localdynamic) alias i32* @thread_var + +; CHECK-LABEL: get_thread_var +define i32* @get_thread_var() { +; CHECK: leal thread_var@TLSGD + ret i32* @thread_var +} + +; CHECK-LABEL: get_thread_alias +define i32* @get_thread_alias() { +; CHECK: leal thread_alias@TLSLD + ret i32* @thread_alias +} @bar = global i32 42 diff --git a/test/Feature/alias2.ll b/test/Feature/alias2.ll index 693ef7c9be..4334a62017 100644 --- a/test/Feature/alias2.ll +++ b/test/Feature/alias2.ll @@ -17,3 +17,6 @@ @v6 = alias i16, i32* @v1 ; CHECK: @v6 = alias i16, i32* @v1 + +@v7 = thread_local(localdynamic) alias i32* @v1 +; CHECK: @v7 = thread_local(localdynamic) alias i32* @v1 |