[llvm] r243438 - Implement target independent TLS compatible with glibc's emutls.c.
Chih-hung Hsieh
chh at google.com
Tue Jul 28 13:32:47 PDT 2015
Thanks. I submitted r243474, which should limit this test case only to
linux.
On Tue, Jul 28, 2015 at 1:08 PM, Sanjay Patel <spatel at rotateright.com>
wrote:
> Hi Chih-hung,
>
> I don't know why it fails on OSX, but I am able to work-around the crash
> by specifying the triple in the RUN line:
> -mtriple=x86_64-unknown-unknown
>
> Conversely, you can probably reproduce the error on your platform by
> specifying a darwin triple:
> -mtriple=x86_64-apple-darwin
>
>
> On Tue, Jul 28, 2015 at 1:40 PM, Chih-hung Hsieh <chh at google.com> wrote:
>
>> I still don't know why this test failed on OSX and I cannot see any error
>> on Linux.
>> Do you know why? If not, maybe I can remove that test case for now.
>> Thanks.
>>
>>
>> On Tue, Jul 28, 2015 at 12:11 PM, Sanjay Patel <spatel at rotateright.com>
>> wrote:
>>
>>> 'make check' is broken after this commit when building on OSX. Let me
>>> know if you need more info:
>>>
>>> FAIL: LLVM :: CodeGen/PowerPC/emutls_generic.ll (4000 of 14310)
>>> ******************** TEST 'LLVM :: CodeGen/PowerPC/emutls_generic.ll'
>>> FAILED ********************
>>> Script:
>>> --
>>> /myllvm/build/./bin/llc <
>>> /myllvm/llvm/test/CodeGen/PowerPC/emutls_generic.ll -emulated-tls
>>> -march=ppc64 -relocation-model=pic | /myllvm/build/./bin/FileCheck
>>> /myllvm/llvm/test/CodeGen/PowerPC/emutls_generic.ll
>>> //myllvm/build/./bin/llc <
>>> /myllvm/llvm/test/CodeGen/PowerPC/emutls_generic.ll -emulated-tls
>>> -march=ppc32 -relocation-model=pic | /myllvm/build/./bin/FileCheck
>>> /myllvm/llvm/test/CodeGen/PowerPC/emutls_generic.ll
>>> --
>>> Exit Code: 2
>>>
>>> Command Output (stderr):
>>> --
>>> Assertion failed: ((!IsEmuTLSVar ||
>>> getObjFileLowering().getDataRelLocalSection()) && "Need relocatable local
>>> section for emulated TLS variables"), function EmitGlobalVariable, file
>>> /myllvm/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp, line 394.
>>> 0 llc 0x000000010fb1cb7e
>>> llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 46
>>> 1 llc 0x000000010fb1e449
>>> PrintStackTraceSignalHandler(void*) + 25
>>> 2 llc 0x000000010fb1b139
>>> llvm::sys::RunSignalHandlers() + 425
>>> 3 llc 0x000000010fb1e7ce SignalHandler(int) + 366
>>> 4 libsystem_platform.dylib 0x00007fff97782f1a _sigtramp + 26
>>> 5 libsystem_platform.dylib 0x0000000000000002 _sigtramp + 1753731330
>>> 6 llc 0x000000010fb1e46b raise + 27
>>> 7 llc 0x000000010fb1e522 abort + 18
>>> 8 llc 0x000000010fb1e501 __assert_rtn + 129
>>> 9 llc 0x000000010ecc0bdb
>>> llvm::AsmPrinter::EmitGlobalVariable(llvm::GlobalVariable const*) + 267
>>> 10 llc 0x000000010ecc6368
>>> llvm::AsmPrinter::doFinalization(llvm::Module&) + 248
>>> 11 llc 0x000000010e5d6a24 (anonymous
>>> namespace)::PPCDarwinAsmPrinter::doFinalization(llvm::Module&) + 3588
>>> 12 llc 0x000000010f417b5c
>>> llvm::FPPassManager::doFinalization(llvm::Module&) + 92
>>> 13 llc 0x000000010f41865a (anonymous
>>> namespace)::MPPassManager::runOnModule(llvm::Module&) + 1946
>>> 14 llc 0x000000010f417cd6
>>> llvm::legacy::PassManagerImpl::run(llvm::Module&) + 310
>>> 15 llc 0x000000010f418bb1
>>> llvm::legacy::PassManager::run(llvm::Module&) + 33
>>> 16 llc 0x000000010dbcfcf3 compileModule(char**,
>>> llvm::LLVMContext&) + 10755
>>> 17 llc 0x000000010dbcd286 main + 230
>>> 18 libdyld.dylib 0x00007fff92b6f5c9 start + 1
>>> 19 libdyld.dylib 0x0000000000000004 start + 1833503292
>>> Stack dump:
>>> 0. Program arguments: /myllvm/build/./bin/llc -emulated-tls
>>> -march=ppc64 -relocation-model=pic
>>> FileCheck error: '-' is empty.
>>>
>>>
>>> On Tue, Jul 28, 2015 at 10:24 AM, Chih-Hung Hsieh <chh at google.com>
>>> wrote:
>>>
>>>> Author: chh
>>>> Date: Tue Jul 28 11:24:05 2015
>>>> New Revision: 243438
>>>>
>>>> URL: http://llvm.org/viewvc/llvm-project?rev=243438&view=rev
>>>> Log:
>>>> Implement target independent TLS compatible with glibc's emutls.c.
>>>>
>>>> The 'common' section TLS is not implemented.
>>>> Current C/C++ TLS variables are not placed in common section.
>>>> DWARF debug info to get the address of TLS variables is not generated
>>>> yet.
>>>>
>>>> clang and driver changes in http://reviews.llvm.org/D10524
>>>>
>>>> Added -femulated-tls flag to select the emulated TLS model,
>>>> which will be used for old targets like Android that do not
>>>> support ELF TLS models.
>>>>
>>>> Added TargetLowering::LowerToTLSEmulatedModel as a target-independent
>>>> function to convert a SDNode of TLS variable address to a function call
>>>> to __emutls_get_address.
>>>>
>>>> Added into lib/Target/*/*ISelLowering.cpp to call
>>>> LowerToTLSEmulatedModel
>>>> for TLSModel::Emulated. Although all targets supporting ELF TLS models
>>>> are
>>>> enhanced, emulated TLS model has been tested only for Android ELF
>>>> targets.
>>>> Modified AsmPrinter.cpp to print the emutls_v.* and emutls_t.*
>>>> variables for
>>>> emulated TLS variables.
>>>> Modified DwarfCompileUnit.cpp to skip some DIE for emulated TLS
>>>> variabls.
>>>>
>>>> TODO: Add proper DIE for emulated TLS variables.
>>>> Added new unit tests with emulated TLS.
>>>>
>>>> Differential Revision: http://reviews.llvm.org/D10522
>>>>
>>>> Added:
>>>> llvm/trunk/test/CodeGen/AArch64/emutls.ll
>>>> llvm/trunk/test/CodeGen/ARM/emutls1.ll
>>>> llvm/trunk/test/CodeGen/Generic/emutls.ll
>>>> llvm/trunk/test/CodeGen/X86/emutls-pic.ll
>>>> llvm/trunk/test/CodeGen/X86/emutls-pie.ll
>>>> llvm/trunk/test/CodeGen/X86/emutls.ll
>>>> llvm/trunk/test/CodeGen/X86/fast-isel-emutls.ll
>>>> llvm/trunk/test/CodeGen/X86/tls-android-negative.ll
>>>> llvm/trunk/test/CodeGen/X86/tls-android.ll
>>>> Modified:
>>>> llvm/trunk/docs/LangRef.rst
>>>> llvm/trunk/include/llvm/CodeGen/AsmPrinter.h
>>>> llvm/trunk/include/llvm/CodeGen/CommandFlags.h
>>>> llvm/trunk/include/llvm/MC/MCObjectFileInfo.h
>>>> llvm/trunk/include/llvm/Target/TargetLowering.h
>>>> llvm/trunk/include/llvm/Target/TargetOptions.h
>>>> llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
>>>> llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
>>>> llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
>>>> llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
>>>> llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
>>>> llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
>>>> llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
>>>> llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp
>>>> llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
>>>> llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
>>>> llvm/trunk/test/CodeGen/AArch64/arm64-tls-dynamic-together.ll
>>>> llvm/trunk/test/CodeGen/ARM/tls-models.ll
>>>> llvm/trunk/test/CodeGen/ARM/tls3.ll
>>>> llvm/trunk/test/CodeGen/X86/tls-models.ll
>>>> llvm/trunk/test/DebugInfo/ARM/tls.ll
>>>> llvm/trunk/test/DebugInfo/X86/tls.ll
>>>> llvm/trunk/test/Transforms/GlobalOpt/tls.ll
>>>>
>>>> Modified: llvm/trunk/docs/LangRef.rst
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/docs/LangRef.rst (original)
>>>> +++ llvm/trunk/docs/LangRef.rst Tue Jul 28 11:24:05 2015
>>>> @@ -494,6 +494,9 @@ model is not supported, or if a better c
>>>> 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.
>>>>
>>>> +For platforms without linker support of ELF TLS model, the
>>>> -femulated-tls
>>>> +flag can be used to generate GCC compatible emulated TLS code.
>>>> +
>>>> .. _namedtypes:
>>>>
>>>> Structure Types
>>>>
>>>> Modified: llvm/trunk/include/llvm/CodeGen/AsmPrinter.h
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/AsmPrinter.h?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/include/llvm/CodeGen/AsmPrinter.h (original)
>>>> +++ llvm/trunk/include/llvm/CodeGen/AsmPrinter.h Tue Jul 28 11:24:05
>>>> 2015
>>>> @@ -238,6 +238,11 @@ public:
>>>> ///
>>>> void EmitJumpTableInfo();
>>>>
>>>> + /// Emit the control variable for an emulated TLS variable.
>>>> + virtual void EmitEmulatedTLSControlVariable(const GlobalVariable *GV,
>>>> + MCSymbol *EmittedSym,
>>>> + bool AllZeroInitValue);
>>>> +
>>>> /// Emit the specified global variable to the .s file.
>>>> virtual void EmitGlobalVariable(const GlobalVariable *GV);
>>>>
>>>>
>>>> Modified: llvm/trunk/include/llvm/CodeGen/CommandFlags.h
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/CommandFlags.h?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/include/llvm/CodeGen/CommandFlags.h (original)
>>>> +++ llvm/trunk/include/llvm/CodeGen/CommandFlags.h Tue Jul 28 11:24:05
>>>> 2015
>>>> @@ -219,6 +219,10 @@ FunctionSections("function-sections",
>>>> cl::desc("Emit functions into separate sections"),
>>>> cl::init(false));
>>>>
>>>> +cl::opt<bool> EmulatedTLS("emulated-tls",
>>>> + cl::desc("Use emulated TLS model"),
>>>> + cl::init(false));
>>>> +
>>>> cl::opt<bool> UniqueSectionNames("unique-section-names",
>>>> cl::desc("Give unique names to every
>>>> section"),
>>>> cl::init(true));
>>>> @@ -260,6 +264,7 @@ static inline TargetOptions InitTargetOp
>>>> Options.DataSections = DataSections;
>>>> Options.FunctionSections = FunctionSections;
>>>> Options.UniqueSectionNames = UniqueSectionNames;
>>>> + Options.EmulatedTLS = EmulatedTLS;
>>>>
>>>> Options.MCOptions = InitMCTargetOptionsFromFlags();
>>>> Options.JTType = JTableType;
>>>>
>>>> Modified: llvm/trunk/include/llvm/MC/MCObjectFileInfo.h
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectFileInfo.h?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/include/llvm/MC/MCObjectFileInfo.h (original)
>>>> +++ llvm/trunk/include/llvm/MC/MCObjectFileInfo.h Tue Jul 28 11:24:05
>>>> 2015
>>>> @@ -216,6 +216,7 @@ public:
>>>> MCSection *getTextSection() const { return TextSection; }
>>>> MCSection *getDataSection() const { return DataSection; }
>>>> MCSection *getBSSSection() const { return BSSSection; }
>>>> + MCSection *getReadOnlySection() const { return ReadOnlySection; }
>>>> MCSection *getLSDASection() const { return LSDASection; }
>>>> MCSection *getCompactUnwindSection() const { return
>>>> CompactUnwindSection; }
>>>> MCSection *getDwarfAbbrevSection() const { return
>>>> DwarfAbbrevSection; }
>>>>
>>>> Modified: llvm/trunk/include/llvm/Target/TargetLowering.h
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/include/llvm/Target/TargetLowering.h (original)
>>>> +++ llvm/trunk/include/llvm/Target/TargetLowering.h Tue Jul 28 11:24:05
>>>> 2015
>>>> @@ -2821,6 +2821,10 @@ public:
>>>> virtual bool useLoadStackGuardNode() const {
>>>> return false;
>>>> }
>>>> +
>>>> + /// Lower TLS global address SDNode for target independent emulated
>>>> TLS model.
>>>> + virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode
>>>> *GA,
>>>> + SelectionDAG &DAG) const;
>>>> };
>>>>
>>>> /// Given an LLVM IR type and return type attributes, compute the
>>>> return value
>>>>
>>>> Modified: llvm/trunk/include/llvm/Target/TargetOptions.h
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetOptions.h?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/include/llvm/Target/TargetOptions.h (original)
>>>> +++ llvm/trunk/include/llvm/Target/TargetOptions.h Tue Jul 28 11:24:05
>>>> 2015
>>>> @@ -72,7 +72,7 @@ namespace llvm {
>>>> UseInitArray(false), DisableIntegratedAS(false),
>>>> CompressDebugSections(false), FunctionSections(false),
>>>> DataSections(false), UniqueSectionNames(true),
>>>> TrapUnreachable(false),
>>>> - FloatABIType(FloatABI::Default),
>>>> + EmulatedTLS(false), FloatABIType(FloatABI::Default),
>>>> AllowFPOpFusion(FPOpFusion::Standard),
>>>> Reciprocals(TargetRecip()),
>>>> JTType(JumpTable::Single),
>>>> ThreadModel(ThreadModel::POSIX) {}
>>>> @@ -172,6 +172,10 @@ namespace llvm {
>>>> /// Emit target-specific trap instruction for 'unreachable' IR
>>>> instructions.
>>>> unsigned TrapUnreachable : 1;
>>>>
>>>> + /// EmulatedTLS - This flag enables emulated TLS model, using
>>>> emutls
>>>> + /// function in the runtime library..
>>>> + unsigned EmulatedTLS : 1;
>>>> +
>>>> /// FloatABIType - This setting is set by -float-abi=xxx option is
>>>> specfied
>>>> /// on the command line. This setting may either be Default, Soft,
>>>> or Hard.
>>>> /// Default selects the target's default behavior. Soft selects
>>>> the ABI for
>>>> @@ -231,6 +235,7 @@ inline bool operator==(const TargetOptio
>>>> ARE_EQUAL(PositionIndependentExecutable) &&
>>>> ARE_EQUAL(UseInitArray) &&
>>>> ARE_EQUAL(TrapUnreachable) &&
>>>> + ARE_EQUAL(EmulatedTLS) &&
>>>> ARE_EQUAL(FloatABIType) &&
>>>> ARE_EQUAL(AllowFPOpFusion) &&
>>>> ARE_EQUAL(Reciprocals) &&
>>>>
>>>> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
>>>> +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Tue Jul 28
>>>> 11:24:05 2015
>>>> @@ -343,8 +343,58 @@ MCSymbol *AsmPrinter::getSymbol(const Gl
>>>> return TM.getSymbol(GV, *Mang);
>>>> }
>>>>
>>>> +static MCSymbol *getOrCreateEmuTLSControlSym(MCSymbol *GVSym,
>>>> MCContext &C) {
>>>> + return C.getOrCreateSymbol(Twine("__emutls_v.") + GVSym->getName());
>>>> +}
>>>> +
>>>> +static MCSymbol *getOrCreateEmuTLSInitSym(MCSymbol *GVSym, MCContext
>>>> &C) {
>>>> + return C.getOrCreateSymbol(Twine("__emutls_t.") + GVSym->getName());
>>>> +}
>>>> +
>>>> +/// EmitEmulatedTLSControlVariable - Emit the control variable for an
>>>> emulated TLS variable.
>>>> +void AsmPrinter::EmitEmulatedTLSControlVariable(const GlobalVariable
>>>> *GV,
>>>> + MCSymbol *EmittedSym,
>>>> + bool AllZeroInitValue)
>>>> {
>>>> + // If there is init value, use .data.rel.local section;
>>>> + // otherwise use the .data section.
>>>> + MCSection *TLSVarSection = const_cast<MCSection*>(
>>>> + (GV->hasInitializer() && !AllZeroInitValue)
>>>> + ? getObjFileLowering().getDataRelLocalSection()
>>>> + : getObjFileLowering().getDataSection());
>>>> + OutStreamer->SwitchSection(TLSVarSection);
>>>> + MCSymbol *GVSym = getSymbol(GV);
>>>> + EmitLinkage(GV, EmittedSym); // same linkage as GV
>>>> + const DataLayout &DL = GV->getParent()->getDataLayout();
>>>> + uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType());
>>>> + unsigned AlignLog = getGVAlignmentLog2(GV, DL);
>>>> + unsigned WordSize = DL.getPointerSize();
>>>> + unsigned Alignment = DL.getPointerABIAlignment();
>>>> + EmitAlignment(Log2_32(Alignment));
>>>> + OutStreamer->EmitLabel(EmittedSym);
>>>> + OutStreamer->EmitIntValue(Size, WordSize);
>>>> + OutStreamer->EmitIntValue((1 << AlignLog), WordSize);
>>>> + OutStreamer->EmitIntValue(0, WordSize);
>>>> + if (GV->hasInitializer() && !AllZeroInitValue) {
>>>> + OutStreamer->EmitSymbolValue(
>>>> + getOrCreateEmuTLSInitSym(GVSym, OutContext), WordSize);
>>>> + } else
>>>> + OutStreamer->EmitIntValue(0, WordSize);
>>>> + if (MAI->hasDotTypeDotSizeDirective())
>>>> + OutStreamer->emitELFSize(cast<MCSymbolELF>(EmittedSym),
>>>> + MCConstantExpr::create(4 * WordSize,
>>>> OutContext));
>>>> + OutStreamer->AddBlankLine(); // End of the __emutls_v.* variable.
>>>> +}
>>>> +
>>>> /// EmitGlobalVariable - Emit the specified global variable to the .s
>>>> file.
>>>> void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
>>>> + bool IsEmuTLSVar =
>>>> + GV->getThreadLocalMode() != llvm::GlobalVariable::NotThreadLocal
>>>> &&
>>>> + TM.Options.EmulatedTLS;
>>>> + assert((!IsEmuTLSVar ||
>>>> getObjFileLowering().getDataRelLocalSection()) &&
>>>> + "Need relocatable local section for emulated TLS variables");
>>>> + assert(!(IsEmuTLSVar && GV->hasCommonLinkage()) &&
>>>> + "No emulated TLS variables in the common section");
>>>> +
>>>> if (GV->hasInitializer()) {
>>>> // Check to see if this is a special global used by LLVM, if so,
>>>> emit it.
>>>> if (EmitSpecialLLVMGlobal(GV))
>>>> @@ -355,7 +405,9 @@ void AsmPrinter::EmitGlobalVariable(cons
>>>> if (GlobalGOTEquivs.count(getSymbol(GV)))
>>>> return;
>>>>
>>>> - if (isVerbose()) {
>>>> + if (isVerbose() && !IsEmuTLSVar) {
>>>> + // When printing the control variable __emutls_v.*,
>>>> + // we don't need to print the original TLS variable name.
>>>> GV->printAsOperand(OutStreamer->GetCommentOS(),
>>>> /*PrintType=*/false, GV->getParent());
>>>> OutStreamer->GetCommentOS() << '\n';
>>>> @@ -363,7 +415,12 @@ void AsmPrinter::EmitGlobalVariable(cons
>>>> }
>>>>
>>>> MCSymbol *GVSym = getSymbol(GV);
>>>> - EmitVisibility(GVSym, GV->getVisibility(), !GV->isDeclaration());
>>>> + MCSymbol *EmittedSym = IsEmuTLSVar ?
>>>> + getOrCreateEmuTLSControlSym(GVSym, OutContext) : GVSym;
>>>> + // getOrCreateEmuTLSControlSym only creates the symbol with name and
>>>> default attributes.
>>>> + // GV's or GVSym's attributes will be used for the EmittedSym.
>>>> +
>>>> + EmitVisibility(EmittedSym, GV->getVisibility(),
>>>> !GV->isDeclaration());
>>>>
>>>> if (!GV->hasInitializer()) // External globals require no extra
>>>> code.
>>>> return;
>>>> @@ -374,7 +431,7 @@ void AsmPrinter::EmitGlobalVariable(cons
>>>> "' is already defined");
>>>>
>>>> if (MAI->hasDotTypeDotSizeDirective())
>>>> - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
>>>> + OutStreamer->EmitSymbolAttribute(EmittedSym, MCSA_ELF_TypeObject);
>>>>
>>>> SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV,
>>>> TM);
>>>>
>>>> @@ -386,6 +443,18 @@ void AsmPrinter::EmitGlobalVariable(cons
>>>> // sections and expected to be contiguous (e.g. ObjC metadata).
>>>> unsigned AlignLog = getGVAlignmentLog2(GV, DL);
>>>>
>>>> + bool AllZeroInitValue = false;
>>>> + const Constant *InitValue = GV->getInitializer();
>>>> + if (isa<ConstantAggregateZero>(InitValue))
>>>> + AllZeroInitValue = true;
>>>> + else {
>>>> + const ConstantInt *InitIntValue = dyn_cast<ConstantInt>(InitValue);
>>>> + if (InitIntValue && InitIntValue->isZero())
>>>> + AllZeroInitValue = true;
>>>> + }
>>>> + if (IsEmuTLSVar)
>>>> + EmitEmulatedTLSControlVariable(GV, EmittedSym, AllZeroInitValue);
>>>> +
>>>> for (const HandlerInfo &HI : Handlers) {
>>>> NamedRegionTimer T(HI.TimerName, HI.TimerGroupName,
>>>> TimePassesIsEnabled);
>>>> HI.Handler->setSymbolSize(GVSym, Size);
>>>> @@ -393,6 +462,8 @@ void AsmPrinter::EmitGlobalVariable(cons
>>>>
>>>> // Handle common and BSS local symbols (.lcomm).
>>>> if (GVKind.isCommon() || GVKind.isBSSLocal()) {
>>>> + assert(!(IsEmuTLSVar && GVKind.isCommon()) &&
>>>> + "No emulated TLS variables in the common section");
>>>> if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
>>>> unsigned Align = 1 << AlignLog;
>>>>
>>>> @@ -437,12 +508,21 @@ void AsmPrinter::EmitGlobalVariable(cons
>>>> return;
>>>> }
>>>>
>>>> - MCSection *TheSection =
>>>> + if (IsEmuTLSVar && AllZeroInitValue)
>>>> + return; // No need of initialization values.
>>>> +
>>>> + MCSymbol *EmittedInitSym = IsEmuTLSVar ?
>>>> + getOrCreateEmuTLSInitSym(GVSym, OutContext) : GVSym;
>>>> + // getOrCreateEmuTLSInitSym only creates the symbol with name and
>>>> default attributes.
>>>> + // GV's or GVSym's attributes will be used for the EmittedInitSym.
>>>> +
>>>> + MCSection *TheSection = IsEmuTLSVar ?
>>>> + getObjFileLowering().getReadOnlySection() :
>>>> getObjFileLowering().SectionForGlobal(GV, GVKind, *Mang, TM);
>>>>
>>>> // Handle the zerofill directive on darwin, which is a special form
>>>> of BSS
>>>> // emission.
>>>> - if (GVKind.isBSSExtern() && MAI->hasMachoZeroFillDirective()) {
>>>> + if (GVKind.isBSSExtern() && MAI->hasMachoZeroFillDirective() &&
>>>> !IsEmuTLSVar) {
>>>> if (Size == 0) Size = 1; // zerofill of 0 bytes is undefined.
>>>>
>>>> // .globl _foo
>>>> @@ -462,7 +542,7 @@ void AsmPrinter::EmitGlobalVariable(cons
>>>> // TLOF class. This will also make it more obvious that stuff like
>>>> // MCStreamer::EmitTBSSSymbol is macho specific and only called from
>>>> macho
>>>> // specific code.
>>>> - if (GVKind.isThreadLocal() && MAI->hasMachoTBSSDirective()) {
>>>> + if (GVKind.isThreadLocal() && MAI->hasMachoTBSSDirective() &&
>>>> !IsEmuTLSVar) {
>>>> // Emit the .tbss symbol
>>>> MCSymbol *MangSym =
>>>> OutContext.getOrCreateSymbol(GVSym->getName() +
>>>> Twine("$tlv$init"));
>>>> @@ -506,16 +586,18 @@ void AsmPrinter::EmitGlobalVariable(cons
>>>>
>>>> OutStreamer->SwitchSection(TheSection);
>>>>
>>>> - EmitLinkage(GV, GVSym);
>>>> + // emutls_t.* symbols are only used in the current compilation unit.
>>>> + if (!IsEmuTLSVar)
>>>> + EmitLinkage(GV, EmittedInitSym);
>>>> EmitAlignment(AlignLog, GV);
>>>>
>>>> - OutStreamer->EmitLabel(GVSym);
>>>> + OutStreamer->EmitLabel(EmittedInitSym);
>>>>
>>>> EmitGlobalConstant(GV->getParent()->getDataLayout(),
>>>> GV->getInitializer());
>>>>
>>>> if (MAI->hasDotTypeDotSizeDirective())
>>>> // .size foo, 42
>>>> - OutStreamer->emitELFSize(cast<MCSymbolELF>(GVSym),
>>>> + OutStreamer->emitELFSize(cast<MCSymbolELF>(EmittedInitSym),
>>>> MCConstantExpr::create(Size, OutContext));
>>>>
>>>> OutStreamer->AddBlankLine();
>>>>
>>>> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (original)
>>>> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp Tue Jul 28
>>>> 11:24:05 2015
>>>> @@ -151,28 +151,32 @@ DIE *DwarfCompileUnit::getOrCreateGlobal
>>>> DIELoc *Loc = new (DIEValueAllocator) DIELoc;
>>>> const MCSymbol *Sym = Asm->getSymbol(Global);
>>>> if (Global->isThreadLocal()) {
>>>> - // FIXME: Make this work with -gsplit-dwarf.
>>>> - unsigned PointerSize = Asm->getDataLayout().getPointerSize();
>>>> - assert((PointerSize == 4 || PointerSize == 8) &&
>>>> - "Add support for other sizes if necessary");
>>>> - // Based on GCC's support for TLS:
>>>> - if (!DD->useSplitDwarf()) {
>>>> - // 1) Start with a constNu of the appropriate pointer size
>>>> - addUInt(*Loc, dwarf::DW_FORM_data1,
>>>> - PointerSize == 4 ? dwarf::DW_OP_const4u :
>>>> dwarf::DW_OP_const8u);
>>>> - // 2) containing the (relocated) offset of the TLS variable
>>>> - // within the module's TLS block.
>>>> - addExpr(*Loc, dwarf::DW_FORM_udata,
>>>> -
>>>> Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym));
>>>> + if (Asm->TM.Options.EmulatedTLS) {
>>>> + // TODO: add debug info for emulated thread local mode.
>>>> } else {
>>>> - addUInt(*Loc, dwarf::DW_FORM_data1,
>>>> dwarf::DW_OP_GNU_const_index);
>>>> - addUInt(*Loc, dwarf::DW_FORM_udata,
>>>> - DD->getAddressPool().getIndex(Sym, /* TLS */ true));
>>>> + // FIXME: Make this work with -gsplit-dwarf.
>>>> + unsigned PointerSize = Asm->getDataLayout().getPointerSize();
>>>> + assert((PointerSize == 4 || PointerSize == 8) &&
>>>> + "Add support for other sizes if necessary");
>>>> + // Based on GCC's support for TLS:
>>>> + if (!DD->useSplitDwarf()) {
>>>> + // 1) Start with a constNu of the appropriate pointer size
>>>> + addUInt(*Loc, dwarf::DW_FORM_data1,
>>>> + PointerSize == 4 ? dwarf::DW_OP_const4u :
>>>> dwarf::DW_OP_const8u);
>>>> + // 2) containing the (relocated) offset of the TLS variable
>>>> + // within the module's TLS block.
>>>> + addExpr(*Loc, dwarf::DW_FORM_udata,
>>>> +
>>>> Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym));
>>>> + } else {
>>>> + addUInt(*Loc, dwarf::DW_FORM_data1,
>>>> dwarf::DW_OP_GNU_const_index);
>>>> + addUInt(*Loc, dwarf::DW_FORM_udata,
>>>> + DD->getAddressPool().getIndex(Sym, /* TLS */ true));
>>>> + }
>>>> + // 3) followed by an OP to make the debugger do a TLS lookup.
>>>> + addUInt(*Loc, dwarf::DW_FORM_data1,
>>>> + DD->useGNUTLSOpcode() ?
>>>> dwarf::DW_OP_GNU_push_tls_address
>>>> + : dwarf::DW_OP_form_tls_address);
>>>> }
>>>> - // 3) followed by an OP to make the debugger do a TLS lookup.
>>>> - addUInt(*Loc, dwarf::DW_FORM_data1,
>>>> - DD->useGNUTLSOpcode() ? dwarf::DW_OP_GNU_push_tls_address
>>>> - : dwarf::DW_OP_form_tls_address);
>>>> } else {
>>>> DD->addArangeLabel(SymbolCU(this, Sym));
>>>> addOpAddress(*Loc, Sym);
>>>>
>>>> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp (original)
>>>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Tue Jul 28
>>>> 11:24:05 2015
>>>> @@ -3044,3 +3044,46 @@ bool TargetLowering::expandFP_TO_SINT(SD
>>>> DAG.getConstant(0, dl, NVT), Ret, ISD::SETLT);
>>>> return true;
>>>> }
>>>> +
>>>>
>>>> +//===----------------------------------------------------------------------===//
>>>> +// Implementation of Emulated TLS Model
>>>>
>>>> +//===----------------------------------------------------------------------===//
>>>> +
>>>> +SDValue TargetLowering::LowerToTLSEmulatedModel(const
>>>> GlobalAddressSDNode *GA,
>>>> + SelectionDAG &DAG)
>>>> const {
>>>> + // Access to address of TLS varialbe xyz is lowered to a function
>>>> call:
>>>> + // __emutls_get_address( address of global variable named
>>>> "__emutls_v.xyz" )
>>>> + EVT PtrVT = getPointerTy(DAG.getDataLayout());
>>>> + PointerType *VoidPtrType = Type::getInt8PtrTy(*DAG.getContext());
>>>> + SDLoc dl(GA);
>>>> +
>>>> + ArgListTy Args;
>>>> + ArgListEntry Entry;
>>>> + std::string NameString = ("__emutls_v." +
>>>> GA->getGlobal()->getName()).str();
>>>> + Module *VariableModule =
>>>> const_cast<Module*>(GA->getGlobal()->getParent());
>>>> + StringRef EmuTlsVarName(NameString);
>>>> + GlobalVariable *EmuTlsVar =
>>>> VariableModule->getNamedGlobal(EmuTlsVarName);
>>>> + if (!EmuTlsVar)
>>>> + EmuTlsVar = dyn_cast_or_null<GlobalVariable>(
>>>> + VariableModule->getOrInsertGlobal(EmuTlsVarName, VoidPtrType));
>>>> + Entry.Node = DAG.getGlobalAddress(EmuTlsVar, dl, PtrVT);
>>>> + Entry.Ty = VoidPtrType;
>>>> + Args.push_back(Entry);
>>>> +
>>>> + SDValue EmuTlsGetAddr =
>>>> DAG.getExternalSymbol("__emutls_get_address", PtrVT);
>>>> +
>>>> + TargetLowering::CallLoweringInfo CLI(DAG);
>>>> + CLI.setDebugLoc(dl).setChain(DAG.getEntryNode());
>>>> + CLI.setCallee(CallingConv::C, VoidPtrType, EmuTlsGetAddr,
>>>> std::move(Args), 0);
>>>> + std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
>>>> +
>>>> + // TLSADDR will be codegen'ed as call. Inform MFI that function has
>>>> calls.
>>>> + // At last for X86 targets, maybe good for other targets too?
>>>> + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
>>>> + MFI->setAdjustsStack(true); // Is this only for X86 target?
>>>> + MFI->setHasCalls(true);
>>>> +
>>>> + assert((GA->getOffset() == 0) &&
>>>> + "Emulated TLS must have zero offset in GlobalAddressSDNode");
>>>> + return CallResult.first;
>>>> +}
>>>>
>>>> Modified: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp (original)
>>>> +++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp Tue Jul 28
>>>> 11:24:05 2015
>>>> @@ -3404,6 +3404,10 @@ AArch64TargetLowering::LowerELFGlobalTLS
>>>> const GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
>>>>
>>>> TLSModel::Model Model =
>>>> getTargetMachine().getTLSModel(GA->getGlobal());
>>>> +
>>>> + if (DAG.getTarget().Options.EmulatedTLS)
>>>> + return LowerToTLSEmulatedModel(GA, DAG);
>>>> +
>>>> if (!EnableAArch64ELFLocalDynamicTLSGeneration) {
>>>> if (Model == TLSModel::LocalDynamic)
>>>> Model = TLSModel::GeneralDynamic;
>>>>
>>>> Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
>>>> +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Tue Jul 28 11:24:05
>>>> 2015
>>>> @@ -2583,6 +2583,8 @@ ARMTargetLowering::LowerGlobalTLSAddress
>>>> assert(Subtarget->isTargetELF() &&
>>>> "TLS not implemented for non-ELF targets");
>>>> GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
>>>> + if (DAG.getTarget().Options.EmulatedTLS)
>>>> + return LowerToTLSEmulatedModel(GA, DAG);
>>>>
>>>> TLSModel::Model model =
>>>> getTargetMachine().getTLSModel(GA->getGlobal());
>>>>
>>>>
>>>> Modified: llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp (original)
>>>> +++ llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp Tue Jul 28 11:24:05
>>>> 2015
>>>> @@ -1723,6 +1723,9 @@ lowerGlobalTLSAddress(SDValue Op, Select
>>>> // Local Exec TLS Model.
>>>>
>>>> GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
>>>> + if (DAG.getTarget().Options.EmulatedTLS)
>>>> + return LowerToTLSEmulatedModel(GA, DAG);
>>>> +
>>>> SDLoc DL(GA);
>>>> const GlobalValue *GV = GA->getGlobal();
>>>> EVT PtrVT = getPointerTy(DAG.getDataLayout());
>>>>
>>>> Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original)
>>>> +++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Tue Jul 28
>>>> 11:24:05 2015
>>>> @@ -2085,6 +2085,9 @@ SDValue PPCTargetLowering::LowerGlobalTL
>>>> // large models could be added if users need it, at the cost of
>>>> // additional complexity.
>>>> GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
>>>> + if (DAG.getTarget().Options.EmulatedTLS)
>>>> + return LowerToTLSEmulatedModel(GA, DAG);
>>>> +
>>>> SDLoc dl(GA);
>>>> const GlobalValue *GV = GA->getGlobal();
>>>> EVT PtrVT = getPointerTy(DAG.getDataLayout());
>>>>
>>>> Modified: llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp (original)
>>>> +++ llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp Tue Jul 28
>>>> 11:24:05 2015
>>>> @@ -1872,6 +1872,9 @@ SDValue SparcTargetLowering::LowerGlobal
>>>> SelectionDAG &DAG)
>>>> const {
>>>>
>>>> GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
>>>> + if (DAG.getTarget().Options.EmulatedTLS)
>>>> + return LowerToTLSEmulatedModel(GA, DAG);
>>>> +
>>>> SDLoc DL(GA);
>>>> const GlobalValue *GV = GA->getGlobal();
>>>> EVT PtrVT = getPointerTy(DAG.getDataLayout());
>>>>
>>>> Modified: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp (original)
>>>> +++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp Tue Jul 28
>>>> 11:24:05 2015
>>>> @@ -2485,6 +2485,8 @@ SDValue SystemZTargetLowering::lowerTLSG
>>>>
>>>> SDValue
>>>> SystemZTargetLowering::lowerGlobalTLSAddress(GlobalAddressSDNode *Node,
>>>> SelectionDAG &DAG)
>>>> const {
>>>> + if (DAG.getTarget().Options.EmulatedTLS)
>>>> + return LowerToTLSEmulatedModel(Node, DAG);
>>>> SDLoc DL(Node);
>>>> const GlobalValue *GV = Node->getGlobal();
>>>> EVT PtrVT = getPointerTy(DAG.getDataLayout());
>>>>
>>>> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
>>>> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Jul 28 11:24:05
>>>> 2015
>>>> @@ -11645,6 +11645,8 @@ X86TargetLowering::LowerGlobalTLSAddress
>>>> auto PtrVT = getPointerTy(DAG.getDataLayout());
>>>>
>>>> if (Subtarget->isTargetELF()) {
>>>> + if (DAG.getTarget().Options.EmulatedTLS)
>>>> + return LowerToTLSEmulatedModel(GA, DAG);
>>>> TLSModel::Model model = DAG.getTarget().getTLSModel(GV);
>>>> switch (model) {
>>>> case TLSModel::GeneralDynamic:
>>>>
>>>> Modified: llvm/trunk/test/CodeGen/AArch64/arm64-tls-dynamic-together.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-tls-dynamic-together.ll?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/AArch64/arm64-tls-dynamic-together.ll
>>>> (original)
>>>> +++ llvm/trunk/test/CodeGen/AArch64/arm64-tls-dynamic-together.ll Tue
>>>> Jul 28 11:24:05 2015
>>>> @@ -1,4 +1,7 @@
>>>> -; RUN: llc -O0 -mtriple=arm64-none-linux-gnu -relocation-model=pic
>>>> -verify-machineinstrs < %s | FileCheck %s
>>>> +; RUN: llc -O0 -mtriple=arm64-none-linux-gnu -relocation-model=pic \
>>>> +; RUN: -verify-machineinstrs < %s | FileCheck -check-prefix=CHECK
>>>> -check-prefix=NOEMU %s
>>>> +; RUN: llc -emulated-tls -O0 -mtriple=arm64-none-linux-gnu
>>>> -relocation-model=pic \
>>>> +; RUN: -verify-machineinstrs < %s | FileCheck -check-prefix=CHECK
>>>> -check-prefix=EMU %s
>>>>
>>>> ; If the .tlsdesccall and blr parts are emitted completely separately
>>>> (even with
>>>> ; glue) then LLVM will separate them quite happily (with a spill at
>>>> O0, hence
>>>> @@ -13,6 +16,40 @@ define i32 @test_generaldynamic() {
>>>> %val = load i32, i32* @general_dynamic_var
>>>> ret i32 %val
>>>>
>>>> -; CHECK: .tlsdesccall general_dynamic_var
>>>> -; CHECK-NEXT: blr {{x[0-9]+}}
>>>> +; NOEMU: .tlsdesccall general_dynamic_var
>>>> +; NOEMU-NEXT: blr {{x[0-9]+}}
>>>> +; NOEMU-NOT: __emutls_v.general_dynamic_var:
>>>> +
>>>> +; EMU: adrp{{.+}}__emutls_v.general_dynamic_var
>>>> +; EMU: bl __emutls_get_address
>>>> +
>>>> +; EMU-NOT: __emutls_v.general_dynamic_var
>>>> +; EMU-NOT: __emutls_t.general_dynamic_var
>>>> +}
>>>> +
>>>> + at emulated_init_var = thread_local global i32 37, align 8
>>>> +
>>>> +define i32 @test_emulated_init() {
>>>> +; COMMON-LABEL: test_emulated_init:
>>>> +
>>>> + %val = load i32, i32* @emulated_init_var
>>>> + ret i32 %val
>>>> +
>>>> +; EMU: adrp{{.+}}__emutls_v.emulated_init_var
>>>> +; EMU: bl __emutls_get_address
>>>> +
>>>> +; EMU-NOT: __emutls_v.general_dynamic_var:
>>>> +
>>>> +; EMU: .align 3
>>>> +; EMU-LABEL: __emutls_v.emulated_init_var:
>>>> +; EMU-NEXT: .xword 4
>>>> +; EMU-NEXT: .xword 8
>>>> +; EMU-NEXT: .xword 0
>>>> +; EMU-NEXT: .xword __emutls_t.emulated_init_var
>>>> +
>>>> +; EMU-LABEL: __emutls_t.emulated_init_var:
>>>> +; EMU-NEXT: .word 37
>>>> }
>>>> +
>>>> +; CHECK-NOT: __emutls_v.general_dynamic_var:
>>>> +; EMU-NOT: __emutls_t.general_dynamic_var
>>>>
>>>> Added: llvm/trunk/test/CodeGen/AArch64/emutls.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/emutls.ll?rev=243438&view=auto
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/AArch64/emutls.ll (added)
>>>> +++ llvm/trunk/test/CodeGen/AArch64/emutls.ll Tue Jul 28 11:24:05 2015
>>>> @@ -0,0 +1,368 @@
>>>> +; RUN: llc -emulated-tls -mtriple=arm-linux-android \
>>>> +; RUN: -relocation-model=pic < %s | FileCheck -check-prefix=ARM32
>>>> %s
>>>> +; RUN: llc -emulated-tls -mtriple=aarch64-linux-android \
>>>> +; RUN: -relocation-model=pic < %s | FileCheck -check-prefix=ARM64
>>>> %s
>>>> +
>>>> +; Copied from X86/emutls.ll
>>>> +
>>>> +; Use my_emutls_get_address like __emutls_get_address.
>>>> + at my_emutls_v_xyz = external global i8*, align 4
>>>> +declare i8* @my_emutls_get_address(i8*)
>>>> +
>>>> +define i32 @my_get_xyz() {
>>>> +; ARM32-LABEL: my_get_xyz:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl my_emutls_get_address(PLT)
>>>> +; ARM32-NEXT: ldr r0, [r0]
>>>> +; ARM64-LABEL: my_get_xyz:
>>>> +; ARM64: adrp x0, :got:my_emutls_v_xyz
>>>> +; ARM64-NEXT: ldr x0, [x0, :got_lo12:my_emutls_v_xyz]
>>>> +; ARM64-NEXT: bl my_emutls_get_address
>>>> +; ARM64-NEXT: ldr w0, [x0]
>>>> +; ARM64-NEXT: ldp x29, x30, [sp]
>>>> +
>>>> +entry:
>>>> + %call = call i8* @my_emutls_get_address(i8* bitcast (i8**
>>>> @my_emutls_v_xyz to i8*))
>>>> + %0 = bitcast i8* %call to i32*
>>>> + %1 = load i32, i32* %0, align 4
>>>> + ret i32 %1
>>>> +}
>>>> +
>>>> + at i1 = thread_local global i32 15
>>>> + at i2 = external thread_local global i32
>>>> + at i3 = internal thread_local global i32 15
>>>> + at i4 = hidden thread_local global i32 15
>>>> + at i5 = external hidden thread_local global i32
>>>> + at s1 = thread_local global i16 15
>>>> + at b1 = thread_local global i8 0
>>>> +
>>>> +define i32 @f1() {
>>>> +; ARM32-LABEL: f1:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: ldr r0, [r0]
>>>> +; ARM64-LABEL: f1:
>>>> +; ARM64: adrp x0, :got:__emutls_v.i1
>>>> +; ARM64-NEXT: ldr x0, [x0, :got_lo12:__emutls_v.i1]
>>>> +; ARM64-NEXT: bl __emutls_get_address
>>>> +; ARM64-NEXT: ldr w0, [x0]
>>>> +; ARM64-NEXT: ldp x29, x30, [sp]
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i1
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +define i32* @f2() {
>>>> +; ARM32-LABEL: f2:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: pop
>>>> +; ARM64-LABEL: f2:
>>>> +; ARM64: adrp x0, :got:__emutls_v.i1
>>>> +; ARM64-NEXT: ldr x0, [x0, :got_lo12:__emutls_v.i1]
>>>> +; ARM64-NEXT: bl __emutls_get_address
>>>> +; ARM64-NEXT: ldp x29, x30, [sp]
>>>> +
>>>> +entry:
>>>> + ret i32* @i1
>>>> +}
>>>> +
>>>> +define i32 @f3() nounwind {
>>>> +; ARM32-LABEL: f3:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: ldr r0, [r0]
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i2
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +define i32* @f4() {
>>>> +; ARM32-LABEL: f4:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: pop
>>>> +
>>>> +entry:
>>>> + ret i32* @i2
>>>> +}
>>>> +
>>>> +define i32 @f5() nounwind {
>>>> +; ARM32-LABEL: f5:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: ldr r0, [r0]
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i3
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +define i32* @f6() {
>>>> +; ARM32-LABEL: f6:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: pop
>>>> +
>>>> +entry:
>>>> + ret i32* @i3
>>>> +}
>>>> +
>>>> +define i32 @f7() {
>>>> +; ARM32-LABEL: f7:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: ldr r0, [r0]
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i4
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +define i32* @f8() {
>>>> +; ARM32-LABEL: f8:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: pop
>>>> +
>>>> +entry:
>>>> + ret i32* @i4
>>>> +}
>>>> +
>>>> +define i32 @f9() {
>>>> +; ARM32-LABEL: f9:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: ldr r0, [r0]
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i5
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +define i32* @f10() {
>>>> +; ARM32-LABEL: f10:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: pop
>>>> +
>>>> +entry:
>>>> + ret i32* @i5
>>>> +}
>>>> +
>>>> +define i16 @f11() {
>>>> +; ARM32-LABEL: f11:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: ldrh r0, [r0]
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i16, i16* @s1
>>>> + ret i16 %tmp1
>>>> +}
>>>> +
>>>> +define i32 @f12() {
>>>> +; ARM32-LABEL: f12:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: ldrsh r0, [r0]
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i16, i16* @s1
>>>> + %tmp2 = sext i16 %tmp1 to i32
>>>> + ret i32 %tmp2
>>>> +}
>>>> +
>>>> +define i8 @f13() {
>>>> +; ARM32-LABEL: f13:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: ldrb r0, [r0]
>>>> +; ARM32-NEXT: pop
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i8, i8* @b1
>>>> + ret i8 %tmp1
>>>> +}
>>>> +
>>>> +define i32 @f14() {
>>>> +; ARM32-LABEL: f14:
>>>> +; ARM32: ldr r0,
>>>> +; ARM32-NEXT: ldr r1,
>>>> +; ARM32: add r0, pc, r0
>>>> +; ARM32-NEXT: ldr r0, [r1, r0]
>>>> +; ARM32-NEXT: bl __emutls_get_address(PLT)
>>>> +; ARM32-NEXT: ldrsb r0, [r0]
>>>> +; ARM32-NEXT: pop
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i8, i8* @b1
>>>> + %tmp2 = sext i8 %tmp1 to i32
>>>> + ret i32 %tmp2
>>>> +}
>>>> +
>>>> +;;;;;;;;;;;;;; 32-bit __emutls_v. and __emutls_t.
>>>> +
>>>> +; ARM32 .section .data.rel.local,
>>>> +; ARM32-LABEL: __emutls_v.i1:
>>>> +; ARM32-NEXT: .long 4
>>>> +; ARM32-NEXT: .long 4
>>>> +; ARM32-NEXT: .long 0
>>>> +; ARM32-NEXT: .long __emutls_t.i1
>>>> +
>>>> +; ARM32 .section .rodata,
>>>> +; ARM32-LABEL: __emutls_t.i1:
>>>> +; ARM32-NEXT: .long 15
>>>> +
>>>> +; ARM32-NOT: __emutls_v.i2
>>>> +
>>>> +; ARM32 .section .data.rel.local,
>>>> +; ARM32-LABEL: __emutls_v.i3:
>>>> +; ARM32-NEXT: .long 4
>>>> +; ARM32-NEXT: .long 4
>>>> +; ARM32-NEXT: .long 0
>>>> +; ARM32-NEXT: .long __emutls_t.i3
>>>> +
>>>> +; ARM32 .section .rodata,
>>>> +; ARM32-LABEL: __emutls_t.i3:
>>>> +; ARM32-NEXT: .long 15
>>>> +
>>>> +; ARM32 .section .data.rel.local,
>>>> +; ARM32-LABEL: __emutls_v.i4:
>>>> +; ARM32-NEXT: .long 4
>>>> +; ARM32-NEXT: .long 4
>>>> +; ARM32-NEXT: .long 0
>>>> +; ARM32-NEXT: .long __emutls_t.i4
>>>> +
>>>> +; ARM32 .section .rodata,
>>>> +; ARM32-LABEL: __emutls_t.i4:
>>>> +; ARM32-NEXT: .long 15
>>>> +
>>>> +; ARM32-NOT: __emutls_v.i5:
>>>> +; ARM32 .hidden __emutls_v.i5
>>>> +; ARM32-NOT: __emutls_v.i5:
>>>> +
>>>> +; ARM32 .section .data.rel.local,
>>>> +; ARM32-LABEL: __emutls_v.s1:
>>>> +; ARM32-NEXT: .long 2
>>>> +; ARM32-NEXT: .long 2
>>>> +; ARM32-NEXT: .long 0
>>>> +; ARM32-NEXT: .long __emutls_t.s1
>>>> +
>>>> +; ARM32 .section .rodata,
>>>> +; ARM32-LABEL: __emutls_t.s1:
>>>> +; ARM32-NEXT: .short 15
>>>> +
>>>> +; ARM32 .section .data.rel.local,
>>>> +; ARM32-LABEL: __emutls_v.b1:
>>>> +; ARM32-NEXT: .long 1
>>>> +; ARM32-NEXT: .long 1
>>>> +; ARM32-NEXT: .long 0
>>>> +; ARM32-NEXT: .long 0
>>>> +
>>>> +; ARM32-NOT: __emutls_t.b1
>>>> +
>>>> +;;;;;;;;;;;;;; 64-bit __emutls_v. and __emutls_t.
>>>> +
>>>> +; ARM64 .section .data.rel.local,
>>>> +; ARM64-LABEL: __emutls_v.i1:
>>>> +; ARM64-NEXT: .xword 4
>>>> +; ARM64-NEXT: .xword 4
>>>> +; ARM64-NEXT: .xword 0
>>>> +; ARM64-NEXT: .xword __emutls_t.i1
>>>> +
>>>> +; ARM64 .section .rodata,
>>>> +; ARM64-LABEL: __emutls_t.i1:
>>>> +; ARM64-NEXT: .word 15
>>>> +
>>>> +; ARM64-NOT: __emutls_v.i2
>>>> +
>>>> +; ARM64 .section .data.rel.local,
>>>> +; ARM64-LABEL: __emutls_v.i3:
>>>> +; ARM64-NEXT: .xword 4
>>>> +; ARM64-NEXT: .xword 4
>>>> +; ARM64-NEXT: .xword 0
>>>> +; ARM64-NEXT: .xword __emutls_t.i3
>>>> +
>>>> +; ARM64 .section .rodata,
>>>> +; ARM64-LABEL: __emutls_t.i3:
>>>> +; ARM64-NEXT: .word 15
>>>> +
>>>> +; ARM64 .section .data.rel.local,
>>>> +; ARM64-LABEL: __emutls_v.i4:
>>>> +; ARM64-NEXT: .xword 4
>>>> +; ARM64-NEXT: .xword 4
>>>> +; ARM64-NEXT: .xword 0
>>>> +; ARM64-NEXT: .xword __emutls_t.i4
>>>> +
>>>> +; ARM64 .section .rodata,
>>>> +; ARM64-LABEL: __emutls_t.i4:
>>>> +; ARM64-NEXT: .word 15
>>>> +
>>>> +; ARM64-NOT: __emutls_v.i5:
>>>> +; ARM64 .hidden __emutls_v.i5
>>>> +; ARM64-NOT: __emutls_v.i5:
>>>> +
>>>> +; ARM64 .section .data.rel.local,
>>>> +; ARM64-LABEL: __emutls_v.s1:
>>>> +; ARM64-NEXT: .xword 2
>>>> +; ARM64-NEXT: .xword 2
>>>> +; ARM64-NEXT: .xword 0
>>>> +; ARM64-NEXT: .xword __emutls_t.s1
>>>> +
>>>> +; ARM64 .section .rodata,
>>>> +; ARM64-LABEL: __emutls_t.s1:
>>>> +; ARM64-NEXT: .hword 15
>>>> +
>>>> +; ARM64 .section .data.rel.local,
>>>> +; ARM64-LABEL: __emutls_v.b1:
>>>> +; ARM64-NEXT: .xword 1
>>>> +; ARM64-NEXT: .xword 1
>>>> +; ARM64-NEXT: .xword 0
>>>> +; ARM64-NEXT: .xword 0
>>>> +
>>>> +; ARM64-NOT: __emutls_t.b1
>>>>
>>>> Added: llvm/trunk/test/CodeGen/ARM/emutls1.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/emutls1.ll?rev=243438&view=auto
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/ARM/emutls1.ll (added)
>>>> +++ llvm/trunk/test/CodeGen/ARM/emutls1.ll Tue Jul 28 11:24:05 2015
>>>> @@ -0,0 +1,31 @@
>>>> +; RUN: llc < %s -emulated-tls -march=arm
>>>> -mtriple=arm-linux-androideabi \
>>>> +; RUN: | FileCheck %s
>>>> +; RUN: llc < %s -emulated-tls -march=arm
>>>> -mtriple=arm-linux-androideabi \
>>>> +; RUN: -relocation-model=pic | FileCheck %s --check-prefix=PIC
>>>> +
>>>> +; Compared with tls1.ll, emulated mode should not use __aeabi_read_tp
>>>> or __tls_get_addr.
>>>> +
>>>> +; CHECK-NOT: _aeabi_read_tp
>>>> +; CHECK-NOT: _tls_get_addr
>>>> +; CHECK: __emutls_get_addr
>>>> +; CHECK-NOT: __aeabi_read_tp
>>>> +; CHECK-NOT: _tls_get_addr
>>>> +
>>>> +; PIC-NOT: _aeabi_read_tp
>>>> +; PIC-NOT: _tls_get_addr
>>>> +; PIC: __emutls_get_addr
>>>> +; PIC-NOT: _aeabi_read_tp
>>>> +; PIC-NOT: _tls_get_addr
>>>> +
>>>> + at i = thread_local global i32 15 ; <i32*> [#uses=2]
>>>> +
>>>> +define i32 @f() {
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i ; <i32> [#uses=1]
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +define i32* @g() {
>>>> +entry:
>>>> + ret i32* @i
>>>> +}
>>>>
>>>> Modified: llvm/trunk/test/CodeGen/ARM/tls-models.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/tls-models.ll?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/ARM/tls-models.ll (original)
>>>> +++ llvm/trunk/test/CodeGen/ARM/tls-models.ll Tue Jul 28 11:24:05 2015
>>>> @@ -1,5 +1,11 @@
>>>> -; RUN: llc -march=arm -mtriple=arm-linux-gnueabi < %s | FileCheck
>>>> -check-prefix=CHECK-NONPIC %s
>>>> -; RUN: llc -march=arm -mtriple=arm-linux-gnueabi -relocation-model=pic
>>>> < %s | FileCheck -check-prefix=CHECK-PIC %s
>>>> +; RUN: llc -march=arm -mtriple=arm-linux-gnueabi < %s \
>>>> +; RUN: | FileCheck -check-prefix=CHECK-NONPIC -check-prefix=COMMON
>>>> %s
>>>> +; RUN: llc -march=arm -mtriple=arm-linux-gnueabi -relocation-model=pic
>>>> < %s \
>>>> +; RUN: | FileCheck -check-prefix=CHECK-PIC -check-prefix=COMMON %s
>>>> +; RUN: llc -emulated-tls -march=arm -mtriple=arm-linux-gnueabi < %s \
>>>> +; RUN: | FileCheck -check-prefix=EMUNONPIC -check-prefix=EMU
>>>> -check-prefix=COMMON %s
>>>> +; RUN: llc -emulated-tls -march=arm -mtriple=arm-linux-gnueabi
>>>> -relocation-model=pic < %s \
>>>> +; RUN: | FileCheck -check-prefix=EMUPIC -check-prefix=EMU
>>>> -check-prefix=COMMON %s
>>>>
>>>>
>>>> @external_gd = external thread_local global i32
>>>> @@ -20,23 +26,23 @@ define i32* @f1() {
>>>> entry:
>>>> ret i32* @external_gd
>>>>
>>>> + ; COMMON-LABEL: f1:
>>>> ; Non-PIC code can use initial-exec, PIC code has to use general
>>>> dynamic.
>>>> - ; CHECK-NONPIC-LABEL: f1:
>>>> ; CHECK-NONPIC: external_gd(GOTTPOFF)
>>>> - ; CHECK-PIC-LABEL: f1:
>>>> ; CHECK-PIC: external_gd(TLSGD)
>>>> + ; EMU: __emutls_get_address
>>>> }
>>>>
>>>> define i32* @f2() {
>>>> entry:
>>>> ret i32* @internal_gd
>>>>
>>>> + ; COMMON-LABEL: f2:
>>>> ; Non-PIC code can use local exec, PIC code can use local dynamic,
>>>> ; but that is not implemented, so falls back to general dynamic.
>>>> - ; CHECK-NONPIC-LABEL: f2:
>>>> ; CHECK-NONPIC: internal_gd(TPOFF)
>>>> - ; CHECK-PIC-LABEL: f2:
>>>> ; CHECK-PIC: internal_gd(TLSGD)
>>>> + ; EMU: __emutls_get_address
>>>> }
>>>>
>>>>
>>>> @@ -46,24 +52,24 @@ define i32* @f3() {
>>>> entry:
>>>> ret i32* @external_ld
>>>>
>>>> + ; COMMON-LABEL: f3:
>>>> ; Non-PIC code can use initial exec, PIC should use local dynamic,
>>>> ; but that is not implemented, so falls back to general dynamic.
>>>> - ; CHECK-NONPIC-LABEL: f3:
>>>> ; CHECK-NONPIC: external_ld(GOTTPOFF)
>>>> - ; CHECK-PIC-LABEL: f3:
>>>> ; CHECK-PIC: external_ld(TLSGD)
>>>> + ; EMU: __emutls_get_address
>>>> }
>>>>
>>>> define i32* @f4() {
>>>> entry:
>>>> ret i32* @internal_ld
>>>>
>>>> + ; COMMON-LABEL: f4:
>>>> ; Non-PIC code can use local exec, PIC code can use local dynamic,
>>>> ; but that is not implemented, so it falls back to general dynamic.
>>>> - ; CHECK-NONPIC-LABEL: f4:
>>>> ; CHECK-NONPIC: internal_ld(TPOFF)
>>>> - ; CHECK-PIC-LABEL: f4:
>>>> ; CHECK-PIC: internal_ld(TLSGD)
>>>> + ; EMU: __emutls_get_address
>>>> }
>>>>
>>>>
>>>> @@ -73,22 +79,22 @@ define i32* @f5() {
>>>> entry:
>>>> ret i32* @external_ie
>>>>
>>>> + ; COMMON-LABEL: f5:
>>>> ; Non-PIC and PIC code will use initial exec as specified.
>>>> - ; CHECK-NONPIC-LABEL: f5:
>>>> ; CHECK-NONPIC: external_ie(GOTTPOFF)
>>>> - ; CHECK-PIC-LABEL: f5:
>>>> ; CHECK-PIC: external_ie(GOTTPOFF)
>>>> + ; EMU: __emutls_get_address
>>>> }
>>>>
>>>> define i32* @f6() {
>>>> entry:
>>>> ret i32* @internal_ie
>>>>
>>>> + ; COMMON-LABEL: f6:
>>>> ; Non-PIC code can use local exec, PIC code use initial exec as
>>>> specified.
>>>> - ; CHECK-NONPIC-LABEL: f6:
>>>> ; CHECK-NONPIC: internal_ie(TPOFF)
>>>> - ; CHECK-PIC-LABEL: f6:
>>>> ; CHECK-PIC: internal_ie(GOTTPOFF)
>>>> + ; EMU: __emutls_get_address
>>>> }
>>>>
>>>>
>>>> @@ -98,20 +104,52 @@ define i32* @f7() {
>>>> entry:
>>>> ret i32* @external_le
>>>>
>>>> + ; COMMON-LABEL: f7:
>>>> ; Non-PIC and PIC code will use local exec as specified.
>>>> - ; CHECK-NONPIC-LABEL: f7:
>>>> ; CHECK-NONPIC: external_le(TPOFF)
>>>> - ; CHECK-PIC-LABEL: f7:
>>>> ; CHECK-PIC: external_le(TPOFF)
>>>> + ; EMU: __emutls_get_address
>>>> }
>>>>
>>>> define i32* @f8() {
>>>> entry:
>>>> ret i32* @internal_le
>>>>
>>>> + ; COMMON-LABEL: f8:
>>>> ; Non-PIC and PIC code will use local exec as specified.
>>>> - ; CHECK-NONPIC-LABEL: f8:
>>>> ; CHECK-NONPIC: internal_le(TPOFF)
>>>> - ; CHECK-PIC-LABEL: f8:
>>>> ; CHECK-PIC: internal_le(TPOFF)
>>>> + ; EMU: __emutls_get_address
>>>> }
>>>> +
>>>> +
>>>> +; ----- emulated specified -----
>>>> +
>>>> +; External declaration has no initializer.
>>>> +; Internal definition has initializer.
>>>> +
>>>> +; EMU-NOT: __emutls_t.external_gd
>>>> +; EMU-NOT: __emutls_v.external_gd
>>>> +; EMU: .align 2
>>>> +; EMU-LABEL: __emutls_v.internal_gd:
>>>> +; EMU-NEXT: .long 4
>>>> +; EMU-NEXT: .long 4
>>>> +; EMU-NEXT: .long 0
>>>> +; EMU-NEXT: .long __emutls_t.internal_gd
>>>> +; EMU-LABEL: __emutls_t.internal_gd:
>>>> +; EMU-NEXT: .long 42
>>>> +; EMU-NOT: __emutls_t.external_gd
>>>> +
>>>> +; __emutls_t and __emutls_v are the same for PIC and non-PIC modes.
>>>> +
>>>> +; EMU-NOT: __emutls_t.external_gd
>>>> +; EMU-NOT: __emutls_v.external_gd
>>>> +; EMU: .align 2
>>>> +; EMU-LABEL: __emutls_v.internal_le:
>>>> +; EMU-NEXT: .long 4
>>>> +; EMU-NEXT: .long 4
>>>> +; EMU-NEXT: .long 0
>>>> +; EMU-NEXT: .long __emutls_t.internal_le
>>>> +; EMU-LABEL: __emutls_t.internal_le:
>>>> +; EMU-NEXT: .long 42
>>>> +; EMU-NOT: __emutls_t.external_le
>>>>
>>>> Modified: llvm/trunk/test/CodeGen/ARM/tls3.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/tls3.ll?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/ARM/tls3.ll (original)
>>>> +++ llvm/trunk/test/CodeGen/ARM/tls3.ll Tue Jul 28 11:24:05 2015
>>>> @@ -1,11 +1,34 @@
>>>> ; RUN: llc < %s -march=arm -mtriple=arm-linux-gnueabi | \
>>>> ; RUN: grep "tbss"
>>>> +; RUN: llc < %s -march=arm -mtriple=arm-linux-gnueabi | \
>>>> +; RUN: FileCheck %s -check-prefix=CHECK -check-prefix=NOEMU
>>>> +; RUN: llc < %s -emulated-tls -march=arm -mtriple=arm-linux-gnueabi | \
>>>> +; RUN: FileCheck %s -check-prefix=CHECK -check-prefix=EMU
>>>>
>>>> %struct.anon = type { i32, i32 }
>>>> - at teste = internal thread_local global %struct.anon zeroinitializer
>>>> ; <%struct.anon*> [#uses=1]
>>>> + at teste = internal thread_local global %struct.anon zeroinitializer ;
>>>> <%struct.anon*> [#uses=1]
>>>>
>>>> define i32 @main() {
>>>> entry:
>>>> - %tmp2 = load i32, i32* getelementptr (%struct.anon,
>>>> %struct.anon* @teste, i32 0, i32 0), align 8 ; <i32>
>>>> [#uses=1]
>>>> - ret i32 %tmp2
>>>> + %tmp2 = load i32, i32* getelementptr (%struct.anon, %struct.anon*
>>>> @teste, i32 0, i32 0), align 8 ; <i32> [#uses=1]
>>>> + ret i32 %tmp2
>>>> }
>>>> +
>>>> +; CHECK-LABEL: main:
>>>> +; NOEMU-NOT: __emutls_get_address
>>>> +
>>>> +; NOEMU: .section .tbss
>>>> +; NOEMU-LABEL: teste:
>>>> +; NOEMU-NEXT: .zero 8
>>>> +
>>>> +; CHECK-NOT: __emutls_t.teste
>>>> +
>>>> +; EMU: .align 2
>>>> +; EMU-LABEL: __emutls_v.teste:
>>>> +; EMU-NEXT: .long 8
>>>> +; EMU-NEXT: .long 4
>>>> +; EMU-NEXT: .long 0
>>>> +; EMU-NEXT: .long 0
>>>> +
>>>> +; CHECK-NOT: teste:
>>>> +; CHECK-NOT: __emutls_t.teste
>>>>
>>>> Added: llvm/trunk/test/CodeGen/Generic/emutls.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Generic/emutls.ll?rev=243438&view=auto
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/Generic/emutls.ll (added)
>>>> +++ llvm/trunk/test/CodeGen/Generic/emutls.ll Tue Jul 28 11:24:05 2015
>>>> @@ -0,0 +1,298 @@
>>>> +; RUN: llc < %s -emulated-tls -mtriple=arm-linux-android
>>>> -relocation-model=pic \
>>>> +; RUN: | FileCheck -check-prefix=ARM_32 %s
>>>> +; RUN: llc < %s -emulated-tls -mtriple=arm-linux-androidabi
>>>> -relocation-model=pic \
>>>> +; RUN: | FileCheck -check-prefix=ARM_32 %s
>>>> +; RUN: llc < %s -emulated-tls -mtriple=aarch64-linux-android
>>>> -relocation-model=pic \
>>>> +; RUN: | FileCheck -check-prefix=ARM_64 %s
>>>> +; RUN: llc < %s -emulated-tls -mtriple=arm-linux-androidabi
>>>> -relocation-model=pic -O3 \
>>>> +; RUN: | FileCheck -check-prefix=ARM_32 %s
>>>> +; RUN: llc < %s -emulated-tls -mtriple=aarch64-linux-android
>>>> -relocation-model=pic -O3 \
>>>> +; RUN: | FileCheck -check-prefix=ARM_64 %s
>>>> +; RUN: llc < %s -emulated-tls -mtriple=arm-linux-androidabi -O3 \
>>>> +; RUN: | FileCheck -check-prefix=ARM_32 %s
>>>> +; RUN: llc < %s -emulated-tls -mtriple=aarch64-linux-android -O3 \
>>>> +; RUN: | FileCheck -check-prefix=ARM_64 %s
>>>> +; RUN: llc < %s -emulated-tls -mtriple=i686-linux-android
>>>> -relocation-model=pic \
>>>> +; RUN: | FileCheck -check-prefix=X86_32 %s
>>>> +; RUN: llc < %s -emulated-tls -mtriple=x86_64-linux-android -march=x86
>>>> -relocation-model=pic \
>>>> +; RUN: | FileCheck -check-prefix=X86_32 %s
>>>> +; RUN: llc < %s -emulated-tls -mtriple=x86_64-linux-android
>>>> -relocation-model=pic \
>>>> +; RUN: | FileCheck -check-prefix=X86_64 %s
>>>> +; RUN: llc < %s -emulated-tls -mtriple=mipsel-linux-android
>>>> -relocation-model=pic \
>>>> +; RUN: | FileCheck -check-prefix=MIPS_32 %s
>>>> +; RUN: llc < %s -emulated-tls -mtriple=mips64el-linux-android
>>>> -relocation-model=pic \
>>>> +; RUN: | FileCheck -check-prefix=MIPS_64 %s
>>>> +; RUN: llc < %s -emulated-tls -march=ppc64 -relocation-model=pic \
>>>> +; RUN: | FileCheck %s
>>>> +; RUN: llc < %s -emulated-tls -march=ppc32 -relocation-model=pic \
>>>> +; RUN: | FileCheck %s
>>>> +; RUN: llc < %s -emulated-tls -march=x86 -mtriple=i386-linux-gnu
>>>> -relocation-model=pic \
>>>> +; RUN: | FileCheck %s
>>>> +
>>>> +; Make sure that TLS symbols are emitted in expected order.
>>>> +
>>>> + at external_x = external thread_local global i32, align 8
>>>> + at external_y = thread_local global i8 7, align 2
>>>> + at internal_y = internal thread_local global i64 9, align 16
>>>> +
>>>> +define i32* @get_external_x() {
>>>> +entry:
>>>> + ret i32* @external_x
>>>> +}
>>>> +
>>>> +define i8* @get_external_y() {
>>>> +entry:
>>>> + ret i8* @external_y
>>>> +}
>>>> +
>>>> +define i64* @get_internal_y() {
>>>> +entry:
>>>> + ret i64* @internal_y
>>>> +}
>>>> +
>>>> +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; targets independent mode
>>>> +; CHECK-LABEL: get_external_x:
>>>> +; CHECK-NOT: _tls_get_address
>>>> +; CHECK: __emutls_get_address
>>>> +; CHECK-LABEL: get_external_y:
>>>> +; CHECK: __emutls_get_address
>>>> +; CHECK-NOT: _tls_get_address
>>>> +; CHECK-LABEL: get_internal_y:
>>>> +
>>>> +; CHECK-NOT: __emutls_t.external_x:
>>>> +; CHECK-NOT: __emutls_v.external_x:
>>>> +
>>>> +; CHECK-LABEL: __emutls_v.external_y:
>>>> +; CHECK-LABEL: __emutls_t.external_y:
>>>> +; CHECK: __emutls_t.external_y
>>>> +
>>>> +; CHECK-LABEL: __emutls_v.internal_y:
>>>> +; CHECK-LABEL: __emutls_t.internal_y:
>>>> +; CHECK: __emutls_t.internal_y
>>>> +
>>>> +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 32-bit mode
>>>> +; ARM_32-LABEL: get_external_x:
>>>> +; X86_32-LABEL: get_external_x:
>>>> +; MIPS-LABEL: get_external_x:
>>>> +
>>>> +; ARM_32: bl __emutls_get_address
>>>> +; ARM_32: .long __emutls_v.external_x
>>>> +
>>>> +; X86_32: movl __emutls_v.external_x
>>>> +; X86_32: calll __emutls_get_address
>>>> +
>>>> +; ARM_32-LABEL: get_external_y:
>>>> +; X86_32-LABEL: get_external_y:
>>>> +; MIPS_32-LABEL: get_external_y:
>>>> +
>>>> +; ARM_32: bl __emutls_get_address
>>>> +; ARM_32: .long __emutls_v.external_y
>>>> +
>>>> +; X86_32: movl __emutls_v.external_y
>>>> +; X86_32: calll __emutls_get_address
>>>> +
>>>> +; ARM_32-LABEL: get_internal_y:
>>>> +; X86_32-LABEL: get_internal_y:
>>>> +; MIPS_32-LABEL: get_internal_y:
>>>> +
>>>> +; ARM_32: bl __emutls_get_address
>>>> +; ARM_32: .long __emutls_v.internal_y
>>>> +
>>>> +; X86_32: movl __emutls_v.internal_y
>>>> +; X86_32: calll __emutls_get_address
>>>> +
>>>> +; MIPS_32: lw {{.+}}(__emutls_v.internal_y
>>>> +; MIPS_32: lw {{.+}}call16(__emutls_get_address
>>>> +
>>>> +; ARM_32-NOT: __emutls_t.external_x
>>>> +; X86_32-NOT: __emutls_t.external_x
>>>> +; MIPS_32-NOT: __emutls_t.external_x
>>>> +
>>>> +; ARM_32-NOT: __emutls_v.external_x:
>>>> +; X86_32-NOT: __emutls_v.external_x:
>>>> +; MIPS_32-NOT: __emutls_v.external_x:
>>>> +
>>>> +; ARM_32: .section .data.rel.local
>>>> +; X86_32: .section .data.rel.local
>>>> +; MIPS_32: .section .data.rel.local
>>>> +
>>>> +; ARM_32: .align 2
>>>> +; X86_32: .align 4
>>>> +; MIPS_32: .align 2
>>>> +
>>>> +; ARM_32-LABEL: __emutls_v.external_y:
>>>> +; X86_32-LABEL: __emutls_v.external_y:
>>>> +; MIPS_32-LABEL: __emutls_v.external_y:
>>>> +
>>>> +; ARM_32-NEXT: .long 1
>>>> +; ARM_32-NEXT: .long 2
>>>> +; ARM_32-NEXT: .long 0
>>>> +; ARM_32-NEXT: .long __emutls_t.external_y
>>>> +
>>>> +; X86_32-NEXT: .long 1
>>>> +; X86_32-NEXT: .long 2
>>>> +; X86_32-NEXT: .long 0
>>>> +; X86_32-NEXT: .long __emutls_t.external_y
>>>> +
>>>> +; ARM_32: .section .rodata,
>>>> +; X86_32: .section .rodata,
>>>> +; MIPS_32: .section .rodata,
>>>> +
>>>> +; ARM_32-LABEL: __emutls_t.external_y:
>>>> +; X86_32-LABEL: __emutls_t.external_y:
>>>> +; MIPS_32-LABEL: __emutls_t.external_y:
>>>> +
>>>> +; ARM_32-NEXT: .byte 7
>>>> +; X86_32-NEXT: .byte 7
>>>> +; MIPS_32-NEXT: .byte 7
>>>> +
>>>> +; ARM_32: .section .data.rel.local
>>>> +; X86_32: .section .data.rel.local
>>>> +; MIPS_32: .section .data.rel.local
>>>> +
>>>> +; ARM_32: .align 2
>>>> +; X86_32: .align 4
>>>> +; MIPS_32: .align 2
>>>> +
>>>> +; ARM_32-LABEL: __emutls_v.internal_y:
>>>> +; X86_32-LABEL: __emutls_v.internal_y:
>>>> +; MIPS_32-LABEL: __emutls_v.internal_y:
>>>> +
>>>> +; ARM_32-NEXT: .long 8
>>>> +; ARM_32-NEXT: .long 16
>>>> +; ARM_32-NEXT: .long 0
>>>> +; ARM_32-NEXT: .long __emutls_t.internal_y
>>>> +
>>>> +; X86_32-NEXT: .long 8
>>>> +; X86_32-NEXT: .long 16
>>>> +; X86_32-NEXT: .long 0
>>>> +; X86_32-NEXT: .long __emutls_t.internal_y
>>>> +
>>>> +; MIPS_32-NEXT: .4byte 8
>>>> +; MIPS_32-NEXT: .4byte 16
>>>> +; MIPS_32-NEXT: .4byte 0
>>>> +; MIPS_32-NEXT: .4byte __emutls_t.internal_y
>>>> +
>>>> +; ARM_32-LABEL: __emutls_t.internal_y:
>>>> +; X86_32-LABEL: __emutls_t.internal_y:
>>>> +; MIPS_32-LABEL: __emutls_t.internal_y:
>>>> +
>>>> +; ARM_32-NEXT: .long 9
>>>> +; ARM_32-NEXT: .long 0
>>>> +; X86_32-NEXT: .quad 9
>>>> +; MIPS_32-NEXT: .8byte 9
>>>> +
>>>> +
>>>> +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 64-bit mode
>>>> +; X86_64-LABEL: get_external_x:
>>>> +; ARM_64-LABEL: get_external_x:
>>>> +; MIPS_64-LABEL: get_external_x:
>>>> +
>>>> +; X86_64: __emutls_v.external_x
>>>> +; X86_64: __emutls_get_address
>>>> +
>>>> +; ARM_64: __emutls_v.external_x
>>>> +; ARM_64: __emutls_get_address
>>>> +
>>>> +; X86_64-LABEL: get_external_y:
>>>> +; ARM_64-LABEL: get_external_y:
>>>> +; MIPS_64-LABEL: get_external_y:
>>>> +
>>>> +; X86_64: __emutls_v.external_y
>>>> +; X86_64: __emutls_get_address
>>>> +
>>>> +; ARM_64: __emutls_v.external_y
>>>> +; ARM_64: __emutls_get_address
>>>> +
>>>> +; X86_64-LABEL: get_internal_y:
>>>> +; ARM_64-LABEL: get_internal_y:
>>>> +; MIPS_64-LABEL: get_internal_y:
>>>> +
>>>> +; X86_64: __emutls_v.internal_y
>>>> +; X86_64: __emutls_get_address
>>>> +
>>>> +; ARM_64: __emutls_v.internal_y
>>>> +; ARM_64: __emutls_get_address
>>>> +
>>>> +; MIPS_64: ld {{.+}}(__emutls_v.internal_y
>>>> +; MIPS_64: ld {{.+}}call16(__emutls_get_address
>>>> +
>>>> +; ARM_64-NOT: __emutls_t.external_x
>>>> +; X86_64-NOT: __emutls_t.external_x
>>>> +; MIPS_64-NOT: __emutls_t.external_x
>>>> +
>>>> +; X86_64-NOT: __emutls_v.external_x:
>>>> +; ARM_64-NOT: __emutls_v.external_x:
>>>> +; MIPS_64-NOT: __emutls_v.external_x:
>>>> +
>>>> +; X86_64: .align 8
>>>> +; ARM_64: .align 3
>>>> +
>>>> +; X86_64-LABEL: __emutls_v.external_y:
>>>> +; ARM_64-LABEL: __emutls_v.external_y:
>>>> +; MIPS_64-LABEL: __emutls_v.external_y:
>>>> +
>>>> +; X86_64-NEXT: .quad 1
>>>> +; X86_64-NEXT: .quad 2
>>>> +; X86_64-NEXT: .quad 0
>>>> +; X86_64-NEXT: .quad __emutls_t.external_y
>>>> +
>>>> +; ARM_64-NEXT: .xword 1
>>>> +; ARM_64-NEXT: .xword 2
>>>> +; ARM_64-NEXT: .xword 0
>>>> +; ARM_64-NEXT: .xword __emutls_t.external_y
>>>> +
>>>> +; X86_64-NOT: __emutls_v.external_x:
>>>> +; ARM_64-NOT: __emutls_v.external_x:
>>>> +; MIPS_64-NOT: __emutls_v.external_x:
>>>> +
>>>> +; ARM_64: .section .rodata,
>>>> +; X86_64: .section .rodata,
>>>> +; MIPS_64: .section .rodata,
>>>> +
>>>> +; X86_64-LABEL: __emutls_t.external_y:
>>>> +; ARM_64-LABEL: __emutls_t.external_y:
>>>> +; MIPS_64-LABEL: __emutls_t.external_y:
>>>> +
>>>> +; X86_64-NEXT: .byte 7
>>>> +; ARM_64-NEXT: .byte 7
>>>> +; MIPS_64-NEXT: .byte 7
>>>> +
>>>> +; ARM_64: .section .data.rel.local
>>>> +; X86_64: .section .data.rel.local
>>>> +; MIPS_64: .section .data.rel.local
>>>> +
>>>> +; X86_64: .align 8
>>>> +; ARM_64: .align 3
>>>> +; MIPS_64: .align 3
>>>> +
>>>> +; X86_64-LABEL: __emutls_v.internal_y:
>>>> +; ARM_64-LABEL: __emutls_v.internal_y:
>>>> +; MIPS_64-LABEL: __emutls_v.internal_y:
>>>> +
>>>> +; X86_64-NEXT: .quad 8
>>>> +; X86_64-NEXT: .quad 16
>>>> +; X86_64-NEXT: .quad 0
>>>> +; X86_64-NEXT: .quad __emutls_t.internal_y
>>>> +
>>>> +; ARM_64-NEXT: .xword 8
>>>> +; ARM_64-NEXT: .xword 16
>>>> +; ARM_64-NEXT: .xword 0
>>>> +; ARM_64-NEXT: .xword __emutls_t.internal_y
>>>> +
>>>> +; MIPS_64-NEXT: .8byte 8
>>>> +; MIPS_64-NEXT: .8byte 16
>>>> +; MIPS_64-NEXT: .8byte 0
>>>> +; MIPS_64-NEXT: .8byte __emutls_t.internal_y
>>>> +
>>>> +; ARM_64: .section .rodata,
>>>> +; X86_64: .section .rodata,
>>>> +; MIPS_64: .section .rodata,
>>>> +
>>>> +; X86_64-LABEL: __emutls_t.internal_y:
>>>> +; ARM_64-LABEL: __emutls_t.internal_y:
>>>> +; MIPS_64-LABEL: __emutls_t.internal_y:
>>>> +
>>>> +; X86_64-NEXT: .quad 9
>>>> +; ARM_64-NEXT: .xword 9
>>>> +; MIPS_64-NEXT: .8byte 9
>>>>
>>>> Added: llvm/trunk/test/CodeGen/X86/emutls-pic.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/emutls-pic.ll?rev=243438&view=auto
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/X86/emutls-pic.ll (added)
>>>> +++ llvm/trunk/test/CodeGen/X86/emutls-pic.ll Tue Jul 28 11:24:05 2015
>>>> @@ -0,0 +1,168 @@
>>>> +; RUN: llc < %s -emulated-tls -march=x86 -mtriple=i386-linux-gnu
>>>> -relocation-model=pic | FileCheck -check-prefix=X32 %s
>>>> +; RUN: llc < %s -emulated-tls -march=x86-64 -mtriple=x86_64-linux-gnu
>>>> -relocation-model=pic | FileCheck -check-prefix=X64 %s
>>>> +; RUN: llc < %s -emulated-tls -march=x86 -mtriple=i386-linux-android
>>>> -relocation-model=pic | FileCheck -check-prefix=X32 %s
>>>> +; RUN: llc < %s -emulated-tls -march=x86-64
>>>> -mtriple=x86_64-linux-android -relocation-model=pic | FileCheck
>>>> -check-prefix=X64 %s
>>>> +
>>>> +; Use my_emutls_get_address like __emutls_get_address.
>>>> + at my_emutls_v_xyz = external global i8*, align 4
>>>> +declare i8* @my_emutls_get_address(i8*)
>>>> +
>>>> +define i32 @my_get_xyz() {
>>>> +; X32-LABEL: my_get_xyz:
>>>> +; X32: movl my_emutls_v_xyz at GOT(%ebx), %eax
>>>> +; X32-NEXT: movl %eax, (%esp)
>>>> +; X32-NEXT: calll my_emutls_get_address at PLT
>>>> +; X64-LABEL: my_get_xyz:
>>>> +; X64: movq my_emutls_v_xyz at GOTPCREL(%rip), %rdi
>>>> +; X64-NEXT: callq my_emutls_get_address at PLT
>>>> +; X64-NEXT: movl (%rax), %eax
>>>> +
>>>> +entry:
>>>> + %call = call i8* @my_emutls_get_address(i8* bitcast (i8**
>>>> @my_emutls_v_xyz to i8*))
>>>> + %0 = bitcast i8* %call to i32*
>>>> + %1 = load i32, i32* %0, align 4
>>>> + ret i32 %1
>>>> +}
>>>> +
>>>> + at i = thread_local global i32 15
>>>> + at j = internal thread_local global i32 42
>>>> + at k = internal thread_local global i32 0, align 8
>>>> +
>>>> +define i32 @f1() {
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +; X32-LABEL: f1:
>>>> +; X32: movl __emutls_v.i at GOT(%ebx), %eax
>>>> +; X32-NEXT: movl %eax, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address at PLT
>>>> +; X64-LABEL: f1:
>>>> +; X64: movq __emutls_v.i at GOTPCREL(%rip), %rdi
>>>> +; X64-NEXT: callq __emutls_get_address at PLT
>>>> +; X64-NEXT: movl (%rax), %eax
>>>> +
>>>> + at i2 = external thread_local global i32
>>>> +
>>>> +define i32* @f2() {
>>>> +entry:
>>>> + ret i32* @i
>>>> +}
>>>> +
>>>> +; X32-LABEL: f2:
>>>> +; X64-LABEL: f2:
>>>> +
>>>> +
>>>> +define i32 @f3() {
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i ; <i32> [#uses=1]
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +; X32-LABEL: f3:
>>>> +; X64-LABEL: f3:
>>>> +
>>>> +
>>>> +define i32* @f4() nounwind {
>>>> +entry:
>>>> + ret i32* @i
>>>> +}
>>>> +
>>>> +; X32-LABEL: f4:
>>>> +; X64-LABEL: f4:
>>>> +
>>>> +
>>>> +define i32 @f5() nounwind {
>>>> +entry:
>>>> + %0 = load i32, i32* @j, align 4
>>>> + %1 = load i32, i32* @k, align 4
>>>> + %add = add nsw i32 %0, %1
>>>> + ret i32 %add
>>>> +}
>>>> +
>>>> +; X32-LABEL: f5:
>>>> +; X32: movl __emutls_v.j at GOT(%ebx), %eax
>>>> +; X32-NEXT: movl %eax, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address at PLT
>>>> +; X32-NEXT: movl (%eax), %esi
>>>> +; X32-NEXT: movl __emutls_v.k at GOT(%ebx), %eax
>>>> +; X32-NEXT: movl %eax, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address at PLT
>>>> +; X32-NEXT: addl (%eax), %esi
>>>> +; X32-NEXT: movl %esi, %eax
>>>> +
>>>> +; X64-LABEL: f5:
>>>> +; X64: movq __emutls_v.j at GOTPCREL(%rip), %rdi
>>>> +; X64-NEXT: callq __emutls_get_address at PLT
>>>> +; X64-NEXT: movl (%rax), %ebx
>>>> +; X64-NEXT: movq __emutls_v.k at GOTPCREL(%rip), %rdi
>>>> +; X64-NEXT: callq __emutls_get_address at PLT
>>>> +; X64-NEXT: addl (%rax), %ebx
>>>> +; X64-NEXT: movl %ebx, %eax
>>>> +
>>>> +;;;;; 32-bit targets
>>>> +
>>>> +; X32: .section .data.rel.local,
>>>> +; X32-LABEL: __emutls_v.i:
>>>> +; X32-NEXT: .long 4
>>>> +; X32-NEXT: .long 4
>>>> +; X32-NEXT: .long 0
>>>> +; X32-NEXT: .long __emutls_t.i
>>>> +
>>>> +; X32: .section .rodata,
>>>> +; X32-LABEL: __emutls_t.i:
>>>> +; X32-NEXT: .long 15
>>>> +
>>>> +; X32: .section .data.rel.local,
>>>> +; X32-LABEL: __emutls_v.j:
>>>> +; X32-NEXT: .long 4
>>>> +; X32-NEXT: .long 4
>>>> +; X32-NEXT: .long 0
>>>> +; X32-NEXT: .long __emutls_t.j
>>>> +
>>>> +; X32: .section .rodata,
>>>> +; X32-LABEL: __emutls_t.j:
>>>> +; X32-NEXT: .long 42
>>>> +
>>>> +; X32: .data
>>>> +; X32-LABEL: __emutls_v.k:
>>>> +; X32-NEXT: .long 4
>>>> +; X32-NEXT: .long 8
>>>> +; X32-NEXT: .long 0
>>>> +; X32-NEXT: .long 0
>>>> +
>>>> +; X32-NOT: __emutls_t.k:
>>>> +
>>>> +;;;;; 64-bit targets
>>>> +
>>>> +; X64: .section .data.rel.local,
>>>> +; X64-LABEL: __emutls_v.i:
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 0
>>>> +; X64-NEXT: .quad __emutls_t.i
>>>> +
>>>> +; X64: .section .rodata,
>>>> +; X64-LABEL: __emutls_t.i:
>>>> +; X64-NEXT: .long 15
>>>> +
>>>> +; X64: .section .data.rel.local,
>>>> +; X64-LABEL: __emutls_v.j:
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 0
>>>> +; X64-NEXT: .quad __emutls_t.j
>>>> +
>>>> +; X64: .section .rodata,
>>>> +; X64-LABEL: __emutls_t.j:
>>>> +; X64-NEXT: .long 42
>>>> +
>>>> +; X64: .data
>>>> +; X64-LABEL: __emutls_v.k:
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 8
>>>> +; X64-NEXT: .quad 0
>>>> +; X64-NEXT: .quad 0
>>>> +
>>>> +; X64-NOT: __emutls_t.k:
>>>>
>>>> Added: llvm/trunk/test/CodeGen/X86/emutls-pie.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/emutls-pie.ll?rev=243438&view=auto
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/X86/emutls-pie.ll (added)
>>>> +++ llvm/trunk/test/CodeGen/X86/emutls-pie.ll Tue Jul 28 11:24:05 2015
>>>> @@ -0,0 +1,131 @@
>>>> +; RUN: llc < %s -emulated-tls -march=x86 -mcpu=generic
>>>> -mtriple=i386-linux-gnu -relocation-model=pic -enable-pie \
>>>> +; RUN: | FileCheck -check-prefix=X32 %s
>>>> +; RUN: llc < %s -emulated-tls -march=x86-64 -mcpu=generic
>>>> -mtriple=x86_64-linux-gnu -relocation-model=pic -enable-pie \
>>>> +; RUN: | FileCheck -check-prefix=X64 %s
>>>> +; RUN: llc < %s -emulated-tls -march=x86 -mcpu=generic
>>>> -mtriple=i386-linux-android -relocation-model=pic -enable-pie \
>>>> +; RUN: | FileCheck -check-prefix=X32 %s
>>>> +; RUN: llc < %s -emulated-tls -march=x86-64 -mcpu=generic
>>>> -mtriple=x86_64-linux-android -relocation-model=pic -enable-pie \
>>>> +; RUN: | FileCheck -check-prefix=X64 %s
>>>> +
>>>> +; Use my_emutls_get_address like __emutls_get_address.
>>>> + at my_emutls_v_xyz = external global i8*, align 4
>>>> +declare i8* @my_emutls_get_address(i8*)
>>>> +
>>>> +define i32 @my_get_xyz() {
>>>> +; X32-LABEL: my_get_xyz:
>>>> +; X32: movl my_emutls_v_xyz at GOT(%ebx), %eax
>>>> +; X32-NEXT: movl %eax, (%esp)
>>>> +; X32-NEXT: calll my_emutls_get_address at PLT
>>>> +; X32-NEXT: movl (%eax), %eax
>>>> +; X32-NEXT: addl $8, %esp
>>>> +; X32-NEXT: popl %ebx
>>>> +; X32-NEXT: retl
>>>> +; X64-LABEL: my_get_xyz:
>>>> +; X64: movq my_emutls_v_xyz at GOTPCREL(%rip), %rdi
>>>> +; X64-NEXT: callq my_emutls_get_address at PLT
>>>> +; X64-NEXT: movl (%rax), %eax
>>>> +; X64-NEXT: popq %rdx
>>>> +; X64-NEXT: retq
>>>> +
>>>> +entry:
>>>> + %call = call i8* @my_emutls_get_address(i8* bitcast (i8**
>>>> @my_emutls_v_xyz to i8*))
>>>> + %0 = bitcast i8* %call to i32*
>>>> + %1 = load i32, i32* %0, align 4
>>>> + ret i32 %1
>>>> +}
>>>> +
>>>> + at i = thread_local global i32 15
>>>> + at i2 = external thread_local global i32
>>>> +
>>>> +define i32 @f1() {
>>>> +; X32-LABEL: f1:
>>>> +; X32: movl __emutls_v.i at GOT(%ebx), %eax
>>>> +; X32-NEXT: movl %eax, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address at PLT
>>>> +; X32-NEXT: movl (%eax), %eax
>>>> +; X32-NEXT: addl $8, %esp
>>>> +; X32-NEXT: popl %ebx
>>>> +; X32-NEXT: retl
>>>> +; X64-LABEL: f1:
>>>> +; X64: movq __emutls_v.i at GOTPCREL(%rip), %rdi
>>>> +; X64-NEXT: callq __emutls_get_address at PLT
>>>> +; X64-NEXT: movl (%rax), %eax
>>>> +; X64-NEXT: popq %rdx
>>>> +; X64-NEXT: retq
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +define i32* @f2() {
>>>> +; X32-LABEL: f2:
>>>> +; X32: movl __emutls_v.i at GOT(%ebx), %eax
>>>> +; X32-NEXT: movl %eax, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address at PLT
>>>> +; X64-LABEL: f2:
>>>> +; X64: movq __emutls_v.i at GOTPCREL(%rip), %rdi
>>>> +; X64-NEXT: callq __emutls_get_address at PLT
>>>> +
>>>> +entry:
>>>> + ret i32* @i
>>>> +}
>>>> +
>>>> +define i32 @f3() {
>>>> +; X32-LABEL: f3:
>>>> +; X32: movl __emutls_v.i2 at GOT(%ebx), %eax
>>>> +; X32-NEXT: movl %eax, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address at PLT
>>>> +; X64-LABEL: f3:
>>>> +; X64: movq __emutls_v.i2 at GOTPCREL(%rip), %rdi
>>>> +; X64-NEXT: callq __emutls_get_address at PLT
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i2
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +define i32* @f4() {
>>>> +; X32-LABEL: f4:
>>>> +; X32: movl __emutls_v.i2 at GOT(%ebx), %eax
>>>> +; X32-NEXT: movl %eax, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address at PLT
>>>> +; X64-LABEL: f4:
>>>> +; X64: movq __emutls_v.i2 at GOTPCREL(%rip), %rdi
>>>> +; X64-NEXT: callq __emutls_get_address at PLT
>>>> +
>>>> +entry:
>>>> + ret i32* @i2
>>>> +}
>>>> +
>>>> +;;;;; 32-bit targets
>>>> +
>>>> +; X32: .section .data.rel.local,
>>>> +; X32-LABEL: __emutls_v.i:
>>>> +; X32-NEXT: .long 4
>>>> +; X32-NEXT: .long 4
>>>> +; X32-NEXT: .long 0
>>>> +; X32-NEXT: .long __emutls_t.i
>>>> +
>>>> +; X32: .section .rodata,
>>>> +; X32-LABEL: __emutls_t.i:
>>>> +; X32-NEXT: .long 15
>>>> +
>>>> +; X32-NOT: __emutls_v.i2
>>>> +; X32-NOT: __emutls_t.i2
>>>> +
>>>> +;;;;; 64-bit targets
>>>> +
>>>> +; X64: .section .data.rel.local,
>>>> +; X64-LABEL: __emutls_v.i:
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 0
>>>> +; X64-NEXT: .quad __emutls_t.i
>>>> +
>>>> +; X64: .section .rodata,
>>>> +; X64-LABEL: __emutls_t.i:
>>>> +; X64-NEXT: .long 15
>>>> +
>>>> +; X64-NOT: __emutls_v.i2
>>>> +; X64-NOT: __emutls_t.i2
>>>>
>>>> Added: llvm/trunk/test/CodeGen/X86/emutls.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/emutls.ll?rev=243438&view=auto
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/X86/emutls.ll (added)
>>>> +++ llvm/trunk/test/CodeGen/X86/emutls.ll Tue Jul 28 11:24:05 2015
>>>> @@ -0,0 +1,347 @@
>>>> +; RUN: llc < %s -emulated-tls -march=x86 -mtriple=i386-linux-gnu |
>>>> FileCheck -check-prefix=X32 %s
>>>> +; RUN: llc < %s -emulated-tls -march=x86-64 -mtriple=x86_64-linux-gnu
>>>> | FileCheck -check-prefix=X64 %s
>>>> +; RUN: llc < %s -emulated-tls -march=x86 -mtriple=x86-linux-android |
>>>> FileCheck -check-prefix=X32 %s
>>>> +; RUN: llc < %s -emulated-tls -march=x86-64
>>>> -mtriple=x86_64-linux-android | FileCheck -check-prefix=X64 %s
>>>> +
>>>> +; Copied from tls.ll; emulated TLS model is not implemented
>>>> +; for *-pc-win32 and *-pc-winows targets yet.
>>>> +
>>>> +; Use my_emutls_get_address like __emutls_get_address.
>>>> + at my_emutls_v_xyz = external global i8*, align 4
>>>> +declare i8* @my_emutls_get_address(i8*)
>>>> +
>>>> +define i32 @my_get_xyz() {
>>>> +; X32-LABEL: my_get_xyz:
>>>> +; X32: movl $my_emutls_v_xyz, (%esp)
>>>> +; X32-NEXT: calll my_emutls_get_address
>>>> +; X32-NEXT: movl (%eax), %eax
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +; X64-LABEL: my_get_xyz:
>>>> +; X64: movl $my_emutls_v_xyz, %edi
>>>> +; X64-NEXT: callq my_emutls_get_address
>>>> +; X64-NEXT: movl (%rax), %eax
>>>> +; X64-NEXT: popq %rdx
>>>> +; X64-NEXT: retq
>>>> +
>>>> +entry:
>>>> + %call = call i8* @my_emutls_get_address(i8* bitcast (i8**
>>>> @my_emutls_v_xyz to i8*))
>>>> + %0 = bitcast i8* %call to i32*
>>>> + %1 = load i32, i32* %0, align 4
>>>> + ret i32 %1
>>>> +}
>>>> +
>>>> + at i1 = thread_local global i32 15
>>>> + at i2 = external thread_local global i32
>>>> + at i3 = internal thread_local global i32 15
>>>> + at i4 = hidden thread_local global i32 15
>>>> + at i5 = external hidden thread_local global i32
>>>> + at s1 = thread_local global i16 15
>>>> + at b1 = thread_local global i8 0
>>>> +
>>>> +define i32 @f1() {
>>>> +; X32-LABEL: f1:
>>>> +; X32: movl $__emutls_v.i1, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: movl (%eax), %eax
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +; X64-LABEL: f1:
>>>> +; X64: movl $__emutls_v.i1, %edi
>>>> +; X64-NEXT: callq __emutls_get_address
>>>> +; X64-NEXT: movl (%rax), %eax
>>>> +; X64-NEXT: popq %rdx
>>>> +; X64-NEXT: retq
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i1
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +define i32* @f2() {
>>>> +; X32-LABEL: f2:
>>>> +; X32: movl $__emutls_v.i1, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +; X64-LABEL: f2:
>>>> +; X64: movl $__emutls_v.i1, %edi
>>>> +; X64-NEXT: callq __emutls_get_address
>>>> +; X64-NEXT: popq %rdx
>>>> +; X64-NEXT: retq
>>>> +
>>>> +entry:
>>>> + ret i32* @i1
>>>> +}
>>>> +
>>>> +define i32 @f3() nounwind {
>>>> +; X32-LABEL: f3:
>>>> +; X32: movl $__emutls_v.i2, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: movl (%eax), %eax
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i2
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +define i32* @f4() {
>>>> +; X32-LABEL: f4:
>>>> +; X32: movl $__emutls_v.i2, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +
>>>> +entry:
>>>> + ret i32* @i2
>>>> +}
>>>> +
>>>> +define i32 @f5() nounwind {
>>>> +; X32-LABEL: f5:
>>>> +; X32: movl $__emutls_v.i3, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: movl (%eax), %eax
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i3
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +define i32* @f6() {
>>>> +; X32-LABEL: f6:
>>>> +; X32: movl $__emutls_v.i3, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +
>>>> +entry:
>>>> + ret i32* @i3
>>>> +}
>>>> +
>>>> +define i32 @f7() {
>>>> +; X32-LABEL: f7:
>>>> +; X32: movl $__emutls_v.i4, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: movl (%eax), %eax
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i4
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +define i32* @f8() {
>>>> +; X32-LABEL: f8:
>>>> +; X32: movl $__emutls_v.i4, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +
>>>> +entry:
>>>> + ret i32* @i4
>>>> +}
>>>> +
>>>> +define i32 @f9() {
>>>> +; X32-LABEL: f9:
>>>> +; X32: movl $__emutls_v.i5, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: movl (%eax), %eax
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i32, i32* @i5
>>>> + ret i32 %tmp1
>>>> +}
>>>> +
>>>> +define i32* @f10() {
>>>> +; X32-LABEL: f10:
>>>> +; X32: movl $__emutls_v.i5, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +
>>>> +entry:
>>>> + ret i32* @i5
>>>> +}
>>>> +
>>>> +define i16 @f11() {
>>>> +; X32-LABEL: f11:
>>>> +; X32: movl $__emutls_v.s1, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: movzwl (%eax), %eax
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i16, i16* @s1
>>>> + ret i16 %tmp1
>>>> +}
>>>> +
>>>> +define i32 @f12() {
>>>> +; X32-LABEL: f12:
>>>> +; X32: movl $__emutls_v.s1, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: movswl (%eax), %eax
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i16, i16* @s1
>>>> + %tmp2 = sext i16 %tmp1 to i32
>>>> + ret i32 %tmp2
>>>> +}
>>>> +
>>>> +define i8 @f13() {
>>>> +; X32-LABEL: f13:
>>>> +; X32: movl $__emutls_v.b1, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: movb (%eax), %al
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i8, i8* @b1
>>>> + ret i8 %tmp1
>>>> +}
>>>> +
>>>> +define i32 @f14() {
>>>> +; X32-LABEL: f14:
>>>> +; X32: movl $__emutls_v.b1, (%esp)
>>>> +; X32-NEXT: calll __emutls_get_address
>>>> +; X32-NEXT: movsbl (%eax), %eax
>>>> +; X32-NEXT: addl $12, %esp
>>>> +; X32-NEXT: retl
>>>> +
>>>> +entry:
>>>> + %tmp1 = load i8, i8* @b1
>>>> + %tmp2 = sext i8 %tmp1 to i32
>>>> + ret i32 %tmp2
>>>> +}
>>>> +
>>>> +;;;;;;;;;;;;;; 32-bit __emutls_v. and __emutls_t.
>>>> +
>>>> +; X32 .section .data.rel.local,
>>>> +; X32-LABEL: __emutls_v.i1:
>>>> +; X32-NEXT: .long 4
>>>> +; X32-NEXT: .long 4
>>>> +; X32-NEXT: .long 0
>>>> +; X32-NEXT: .long __emutls_t.i1
>>>> +
>>>> +; X32 .section .rodata,
>>>> +; X32-LABEL: __emutls_t.i1:
>>>> +; X32-NEXT: .long 15
>>>> +
>>>> +; X32-NOT: __emutls_v.i2
>>>> +
>>>> +; X32 .section .data.rel.local,
>>>> +; X32-LABEL: __emutls_v.i3:
>>>> +; X32-NEXT: .long 4
>>>> +; X32-NEXT: .long 4
>>>> +; X32-NEXT: .long 0
>>>> +; X32-NEXT: .long __emutls_t.i3
>>>> +
>>>> +; X32 .section .rodata,
>>>> +; X32-LABEL: __emutls_t.i3:
>>>> +; X32-NEXT: .long 15
>>>> +
>>>> +; X32 .section .data.rel.local,
>>>> +; X32-LABEL: __emutls_v.i4:
>>>> +; X32-NEXT: .long 4
>>>> +; X32-NEXT: .long 4
>>>> +; X32-NEXT: .long 0
>>>> +; X32-NEXT: .long __emutls_t.i4
>>>> +
>>>> +; X32 .section .rodata,
>>>> +; X32-LABEL: __emutls_t.i4:
>>>> +; X32-NEXT: .long 15
>>>> +
>>>> +; X32-NOT: __emutls_v.i5:
>>>> +; X32 .hidden __emutls_v.i5
>>>> +; X32-NOT: __emutls_v.i5:
>>>> +
>>>> +; X32 .section .data.rel.local,
>>>> +; X32-LABEL: __emutls_v.s1:
>>>> +; X32-NEXT: .long 2
>>>> +; X32-NEXT: .long 2
>>>> +; X32-NEXT: .long 0
>>>> +; X32-NEXT: .long __emutls_t.s1
>>>> +
>>>> +; X32 .section .rodata,
>>>> +; X32-LABEL: __emutls_t.s1:
>>>> +; X32-NEXT: .short 15
>>>> +
>>>> +; X32 .section .data.rel.local,
>>>> +; X32-LABEL: __emutls_v.b1:
>>>> +; X32-NEXT: .long 1
>>>> +; X32-NEXT: .long 1
>>>> +; X32-NEXT: .long 0
>>>> +; X32-NEXT: .long 0
>>>> +
>>>> +; X32-NOT: __emutls_t.b1
>>>> +
>>>> +;;;;;;;;;;;;;; 64-bit __emutls_v. and __emutls_t.
>>>> +
>>>> +; X64 .section .data.rel.local,
>>>> +; X64-LABEL: __emutls_v.i1:
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 0
>>>> +; X64-NEXT: .quad __emutls_t.i1
>>>> +
>>>> +; X64 .section .rodata,
>>>> +; X64-LABEL: __emutls_t.i1:
>>>> +; X64-NEXT: .long 15
>>>> +
>>>> +; X64-NOT: __emutls_v.i2
>>>> +
>>>> +; X64 .section .data.rel.local,
>>>> +; X64-LABEL: __emutls_v.i3:
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 0
>>>> +; X64-NEXT: .quad __emutls_t.i3
>>>> +
>>>> +; X64 .section .rodata,
>>>> +; X64-LABEL: __emutls_t.i3:
>>>> +; X64-NEXT: .long 15
>>>> +
>>>> +; X64 .section .data.rel.local,
>>>> +; X64-LABEL: __emutls_v.i4:
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 0
>>>> +; X64-NEXT: .quad __emutls_t.i4
>>>> +
>>>> +; X64 .section .rodata,
>>>> +; X64-LABEL: __emutls_t.i4:
>>>> +; X64-NEXT: .long 15
>>>> +
>>>> +; X64-NOT: __emutls_v.i5:
>>>> +; X64 .hidden __emutls_v.i5
>>>> +; X64-NOT: __emutls_v.i5:
>>>> +
>>>> +; X64 .section .data.rel.local,
>>>> +; X64-LABEL: __emutls_v.s1:
>>>> +; X64-NEXT: .quad 2
>>>> +; X64-NEXT: .quad 2
>>>> +; X64-NEXT: .quad 0
>>>> +; X64-NEXT: .quad __emutls_t.s1
>>>> +
>>>> +; X64 .section .rodata,
>>>> +; X64-LABEL: __emutls_t.s1:
>>>> +; X64-NEXT: .short 15
>>>> +
>>>> +; X64 .section .data.rel.local,
>>>> +; X64-LABEL: __emutls_v.b1:
>>>> +; X64-NEXT: .quad 1
>>>> +; X64-NEXT: .quad 1
>>>> +; X64-NEXT: .quad 0
>>>> +; X64-NEXT: .quad 0
>>>> +
>>>> +; X64-NOT: __emutls_t.b1
>>>>
>>>> Added: llvm/trunk/test/CodeGen/X86/fast-isel-emutls.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fast-isel-emutls.ll?rev=243438&view=auto
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/X86/fast-isel-emutls.ll (added)
>>>> +++ llvm/trunk/test/CodeGen/X86/fast-isel-emutls.ll Tue Jul 28 11:24:05
>>>> 2015
>>>> @@ -0,0 +1,48 @@
>>>> +; RUN: llc < %s -emulated-tls -march=x86 -relocation-model=pic
>>>> -mtriple=i686-unknown-linux-gnu -fast-isel | FileCheck %s
>>>> +; PR3654
>>>> +
>>>> + at v = thread_local global i32 0
>>>> +define i32 @f() nounwind {
>>>> +entry:
>>>> + %t = load i32, i32* @v
>>>> + %s = add i32 %t, 1
>>>> + ret i32 %s
>>>> +}
>>>> +
>>>> +; CHECK-LABEL: f:
>>>> +; CHECK: movl __emutls_v.v at GOT(%ebx), %eax
>>>> +; CHECK-NEXT: movl %eax, (%esp)
>>>> +; CHECK-NEXT: calll __emutls_get_address at PLT
>>>> +; CHECK-NEXT: movl (%eax), %eax
>>>> +
>>>> + at alias = internal alias i32* @v
>>>> +define i32 @f_alias() nounwind {
>>>> +entry:
>>>> + %t = load i32, i32* @v
>>>> + %s = add i32 %t, 1
>>>> + ret i32 %s
>>>> +}
>>>> +
>>>> +; CHECK-LABEL: f_alias:
>>>> +; CHECK: movl __emutls_v.v at GOT(%ebx), %eax
>>>> +; CHECK-NEXT: movl %eax, (%esp)
>>>> +; CHECK-NEXT: calll __emutls_get_address at PLT
>>>> +; CHECK-NEXT: movl (%eax), %eax
>>>> +
>>>> +; Use my_emutls_get_address like __emutls_get_address.
>>>> + at my_emutls_v_xyz = external global i8*, align 4
>>>> +declare i8* @my_emutls_get_address(i8*)
>>>> +
>>>> +define i32 @my_get_xyz() {
>>>> +entry:
>>>> + %call = call i8* @my_emutls_get_address(i8* bitcast (i8**
>>>> @my_emutls_v_xyz to i8*))
>>>> + %0 = bitcast i8* %call to i32*
>>>> + %1 = load i32, i32* %0, align 4
>>>> + ret i32 %1
>>>> +}
>>>> +
>>>> +; CHECK-LABEL: my_get_xyz:
>>>> +; CHECK: movl my_emutls_v_xyz at GOT(%ebx), %eax
>>>> +; CHECK-NEXT: movl %eax, (%esp)
>>>> +; CHECK-NEXT: calll my_emutls_get_address at PLT
>>>> +; CHECK-NEXT: movl (%eax), %eax
>>>>
>>>> Added: llvm/trunk/test/CodeGen/X86/tls-android-negative.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tls-android-negative.ll?rev=243438&view=auto
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/X86/tls-android-negative.ll (added)
>>>> +++ llvm/trunk/test/CodeGen/X86/tls-android-negative.ll Tue Jul 28
>>>> 11:24:05 2015
>>>> @@ -0,0 +1,65 @@
>>>> +; RUN: llc < %s -emulated-tls -march=x86 -mtriple=x86_64-linux-android
>>>> -relocation-model=pic | FileCheck %s
>>>> +; RUN: llc < %s -emulated-tls -march=x86-64
>>>> -mtriple=x86_64-linux-android -relocation-model=pic | FileCheck %s
>>>> +
>>>> +; Make sure that some symboles are not emitted in emulated TLS model.
>>>> +
>>>> + at external_x = external thread_local global i32
>>>> + at external_y = thread_local global i32 7
>>>> + at internal_y = internal thread_local global i32 9
>>>> + at internal_y0 = internal thread_local global i32 0
>>>> +
>>>> +define i32* @get_external_x() {
>>>> +entry:
>>>> + ret i32* @external_x
>>>> +}
>>>> +
>>>> +define i32* @get_external_y() {
>>>> +entry:
>>>> + ret i32* @external_y
>>>> +}
>>>> +
>>>> +define i32* @get_internal_y() {
>>>> +entry:
>>>> + ret i32* @internal_y
>>>> +}
>>>> +
>>>> +define i32* @get_internal_y0() {
>>>> +entry:
>>>> + ret i32* @internal_y0
>>>> +}
>>>> +
>>>> +; no direct access to emulated TLS variables.
>>>> +; no definition of emulated TLS variables.
>>>> +; no initializer for external TLS variables, __emutls_t.external_x
>>>> +; no initializer for 0-initialized TLS variables,
>>>> __emutls_t.internal_y0
>>>> +; not global linkage for __emutls_t.external_y
>>>> +
>>>> +; CHECK-NOT: external_x at TLS
>>>> +; CHECK-NOT: external_y at TLS
>>>> +; CHECK-NOT: internal_y at TLS
>>>> +; CHECK-NOT: .size external_x
>>>> +; CHECK-NOT: .size external_y
>>>> +; CHECK-NOT: .size internal_y
>>>> +; CHECK-NOT: .size internal_y0
>>>> +; CHECK-NOT: __emutls_v.external_x:
>>>> +; CHECK-NOT: __emutls_t.external_x:
>>>> +; CHECK-NOT: __emutls_t.internal_y0:
>>>> +; CHECK-NOT: global __emutls_t.external_y
>>>> +; CHECK-NOT: global __emutls_v.internal_y
>>>> +; CHECK-NOT: global __emutls_v.internal_y0
>>>> +
>>>> +; CHECK: __emutls_t.external_y
>>>> +
>>>> +; CHECK-NOT: external_x at TLS
>>>> +; CHECK-NOT: external_y at TLS
>>>> +; CHECK-NOT: internal_y at TLS
>>>> +; CHECK-NOT: .size external_x
>>>> +; CHECK-NOT: .size external_y
>>>> +; CHECK-NOT: .size internal_y
>>>> +; CHECK-NOT: .size internal_y0
>>>> +; CHECK-NOT: __emutls_v.external_x:
>>>> +; CHECK-NOT: __emutls_t.external_x:
>>>> +; CHECK-NOT: __emutls_t.internal_y0:
>>>> +; CHECK-NOT: global __emutls_t.external_y
>>>> +; CHECK-NOT: global __emutls_v.internal_y
>>>> +; CHECK-NOT: global __emutls_v.internal_y0
>>>>
>>>> Added: llvm/trunk/test/CodeGen/X86/tls-android.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tls-android.ll?rev=243438&view=auto
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/X86/tls-android.ll (added)
>>>> +++ llvm/trunk/test/CodeGen/X86/tls-android.ll Tue Jul 28 11:24:05 2015
>>>> @@ -0,0 +1,89 @@
>>>> +; RUN: llc < %s -emulated-tls -march=x86 -mtriple=x86_64-linux-android
>>>> -relocation-model=pic | FileCheck %s
>>>> +; RUN: llc < %s -emulated-tls -march=x86-64
>>>> -mtriple=x86_64-linux-android -relocation-model=pic | FileCheck
>>>> -check-prefix=X64 %s
>>>> +
>>>> +; Make sure that TLS symboles are emitted in expected order.
>>>> +
>>>> + at external_x = external thread_local global i32
>>>> + at external_y = thread_local global i32 7
>>>> + at internal_y = internal thread_local global i32 9
>>>> +
>>>> +define i32* @get_external_x() {
>>>> +entry:
>>>> + ret i32* @external_x
>>>> +}
>>>> +
>>>> +define i32* @get_external_y() {
>>>> +entry:
>>>> + ret i32* @external_y
>>>> +}
>>>> +
>>>> +define i32* @get_internal_y() {
>>>> +entry:
>>>> + ret i32* @internal_y
>>>> +}
>>>> +
>>>> +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 32-bit mode
>>>> +; CHECK-LABEL: get_external_x:
>>>> +; CHECK: __emutls_v.external_x
>>>> +; CHECK: __emutls_get_address
>>>> +
>>>> +; CHECK-LABEL: get_external_y:
>>>> +; CHECK: __emutls_v.external_y
>>>> +; CHECK: __emutls_get_address
>>>> +
>>>> +; CHECK-LABEL: get_internal_y:
>>>> +; CHECK: __emutls_v.internal_y
>>>> +; CHECK: __emutls_get_address
>>>> +
>>>> +; CHECK-NOT: __emutls_v.external_x:
>>>> +
>>>> +; CHECK: .align 4
>>>> +; CHECK-LABEL: __emutls_v.external_y:
>>>> +; CHECK-NEXT: .long 4
>>>> +; CHECK-NEXT: .long 4
>>>> +; CHECK-NEXT: .long 0
>>>> +; CHECK-NEXT: .long __emutls_t.external_y
>>>> +; CHECK-LABEL: __emutls_t.external_y:
>>>> +; CHECK-NEXT: .long 7
>>>> +
>>>> +; CHECK: .align 4
>>>> +; CHECK-LABEL: __emutls_v.internal_y:
>>>> +; CHECK-NEXT: .long 4
>>>> +; CHECK-NEXT: .long 4
>>>> +; CHECK-NEXT: .long 0
>>>> +; CHECK-NEXT: .long __emutls_t.internal_y
>>>> +; CHECK-LABEL: __emutls_t.internal_y:
>>>> +; CHECK-NEXT: .long 9
>>>> +
>>>> +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 64-bit mode
>>>> +; X64-LABEL: get_external_x:
>>>> +; X64: __emutls_v.external_x
>>>> +; X64: __emutls_get_address
>>>> +
>>>> +; X64-LABEL: get_external_y:
>>>> +; X64: __emutls_v.external_y
>>>> +; X64: __emutls_get_address
>>>> +
>>>> +; X64-LABEL: get_internal_y:
>>>> +; X64: __emutls_v.internal_y
>>>> +; X64: __emutls_get_address
>>>> +
>>>> +; X64-NOT: __emutls_v.external_x:
>>>> +
>>>> +; X64: .align 8
>>>> +; X64-LABEL: __emutls_v.external_y:
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 0
>>>> +; X64-NEXT: .quad __emutls_t.external_y
>>>> +; X64-LABEL: __emutls_t.external_y:
>>>> +; X64-NEXT: .long 7
>>>> +
>>>> +; X64: .align 8
>>>> +; X64-LABEL: __emutls_v.internal_y:
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 4
>>>> +; X64-NEXT: .quad 0
>>>> +; X64-NEXT: .quad __emutls_t.internal_y
>>>> +; X64-LABEL: __emutls_t.internal_y:
>>>> +; X64-NEXT: .long 9
>>>>
>>>> Modified: llvm/trunk/test/CodeGen/X86/tls-models.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tls-models.ll?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/X86/tls-models.ll (original)
>>>> +++ llvm/trunk/test/CodeGen/X86/tls-models.ll Tue Jul 28 11:24:05 2015
>>>> @@ -18,6 +18,8 @@
>>>> @external_le = external thread_local(localexec) global i32
>>>> @internal_le = internal thread_local(localexec) global i32 42
>>>>
>>>> +; See test cases for emulated model in emutls.ll, emutls-pic.ll and
>>>> emutls-pie.ll.
>>>> +
>>>> ; ----- no model specified -----
>>>>
>>>> define i32* @f1() {
>>>>
>>>> Modified: llvm/trunk/test/DebugInfo/ARM/tls.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/ARM/tls.ll?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/DebugInfo/ARM/tls.ll (original)
>>>> +++ llvm/trunk/test/DebugInfo/ARM/tls.ll Tue Jul 28 11:24:05 2015
>>>> @@ -1,5 +1,8 @@
>>>> -; RUN: llc -O0 -filetype=asm -mtriple=armv7-linux-gnuehabi < %s |
>>>> FileCheck %s
>>>> -;
>>>> +; RUN: llc -O0 -filetype=asm -mtriple=armv7-linux-gnuehabi < %s \
>>>> +; RUN: | FileCheck %s --check-prefix=CHECK
>>>> +; RUN: llc -O0 -filetype=asm -mtriple=armv7-linux-gnuehabi
>>>> -emulated-tls < %s \
>>>> +; RUN: | FileCheck %s --check-prefix=EMU
>>>> +
>>>> ; Generated with clang with source
>>>> ; __thread int x;
>>>>
>>>> @@ -16,6 +19,9 @@
>>>> ; The debug relocation of the address of the tls variable
>>>> ; CHECK: .long x(tlsldo)
>>>>
>>>> +; TODO: Add expected output for -emulated-tls tests.
>>>> +; EMU-NOT: .long x(tlsldo)
>>>> +
>>>> !0 = !DICompileUnit(language: DW_LANG_C99, producer: "clang version
>>>> 3.5 ", isOptimized: false, emissionKind: 0, file: !1, enums: !2,
>>>> retainedTypes: !2, subprograms: !2, globals: !3, imports: !2)
>>>> !1 = !DIFile(filename: "tls.c", directory: "/tmp")
>>>> !2 = !{}
>>>>
>>>> Modified: llvm/trunk/test/DebugInfo/X86/tls.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/tls.ll?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/DebugInfo/X86/tls.ll (original)
>>>> +++ llvm/trunk/test/DebugInfo/X86/tls.ll Tue Jul 28 11:24:05 2015
>>>> @@ -1,20 +1,30 @@
>>>> ; RUN: llc %s -o - -filetype=asm -O0 -mtriple=x86_64-unknown-linux-gnu
>>>> \
>>>> -; RUN: | FileCheck --check-prefix=SINGLE --check-prefix=SINGLE-64
>>>> --check-prefix=GNUOP %s
>>>> +; RUN: | FileCheck --check-prefix=NOEMU --check-prefix=SINGLE
>>>> --check-prefix=SINGLE-64 --check-prefix=GNUOP %s
>>>>
>>>> ; RUN: llc %s -o - -filetype=asm -O0 -mtriple=i386-linux-gnu \
>>>> -; RUN: | FileCheck --check-prefix=SINGLE --check-prefix=SINGLE-32
>>>> --check-prefix=GNUOP %s
>>>> +; RUN: | FileCheck --check-prefix=NOEMU --check-prefix=SINGLE
>>>> --check-prefix=SINGLE-32 --check-prefix=GNUOP %s
>>>>
>>>> ; RUN: llc %s -o - -filetype=asm -O0 -mtriple=x86_64-unknown-linux-gnu
>>>> -split-dwarf=Enable \
>>>> -; RUN: | FileCheck --check-prefix=FISSION --check-prefix=GNUOP %s
>>>> +; RUN: | FileCheck --check-prefix=NOEMU --check-prefix=FISSION
>>>> --check-prefix=GNUOP %s
>>>>
>>>> ; RUN: llc %s -o - -filetype=asm -O0 -mtriple=x86_64-scei-ps4 \
>>>> -; RUN: | FileCheck --check-prefix=SINGLE --check-prefix=SINGLE-64
>>>> --check-prefix=STDOP %s
>>>> +; RUN: | FileCheck --check-prefix=NOEMU --check-prefix=SINGLE
>>>> --check-prefix=SINGLE-64 --check-prefix=STDOP %s
>>>>
>>>> ; RUN: llc %s -o - -filetype=asm -O0 -mtriple=x86_64-apple-darwin \
>>>> -; RUN: | FileCheck --check-prefix=DARWIN --check-prefix=STDOP %s
>>>> +; RUN: | FileCheck --check-prefix=NOEMU --check-prefix=DARWIN
>>>> --check-prefix=STDOP %s
>>>>
>>>> ; RUN: llc %s -o - -filetype=asm -O0 -mtriple=x86_64-unknown-freebsd \
>>>> -; RUN: | FileCheck --check-prefix=SINGLE --check-prefix=SINGLE-64
>>>> --check-prefix=STDOP %s
>>>> +; RUN: | FileCheck --check-prefix=NOEMU --check-prefix=SINGLE
>>>> --check-prefix=SINGLE-64 --check-prefix=STDOP %s
>>>> +
>>>> +; RUN: llc %s -o - -filetype=asm -O0 -mtriple=x86_64-unknown-linux-gnu
>>>> -emulated-tls \
>>>> +; RUN: | FileCheck --check-prefix=SINGLE --check-prefix=EMUSINGLE-64
>>>> \
>>>> +; RUN: --check-prefix=EMUGNUOP --check-prefix=EMU %s
>>>> +
>>>> +; RUN: llc %s -o - -filetype=asm -O0 -mtriple=i386-linux-gnu
>>>> -emulated-tls \
>>>> +; RUN: | FileCheck --check-prefix=SINGLE --check-prefix=EMUSINGLE-32
>>>> \
>>>> +; RUN: --check-prefix=EMUGNUOP --check-prefix=EMU %s
>>>> +
>>>> +; TODO: Add expected output for -emulated-tls tests.
>>>>
>>>> ; FIXME: add relocation and DWARF expression support to llvm-dwarfdump
>>>> & use
>>>> ; that here instead of raw assembly printing
>>>>
>>>> Modified: llvm/trunk/test/Transforms/GlobalOpt/tls.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/tls.ll?rev=243438&r1=243437&r2=243438&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/Transforms/GlobalOpt/tls.ll (original)
>>>> +++ llvm/trunk/test/Transforms/GlobalOpt/tls.ll Tue Jul 28 11:24:05 2015
>>>> @@ -1,4 +1,5 @@
>>>> ; RUN: opt < %s -globalopt -S | FileCheck %s
>>>> +; RUN: opt -emulated-tls < %s -globalopt -S | FileCheck %s
>>>>
>>>> declare void @wait()
>>>> declare void @signal()
>>>>
>>>>
>>>> _______________________________________________
>>>> llvm-commits mailing list
>>>> llvm-commits at cs.uiuc.edu
>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>>>
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150728/0f6dd398/attachment.html>
More information about the llvm-commits
mailing list