From d4a19b6a72d19a6f90b676aac37118664b7b7a84 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Sat, 11 Feb 2012 17:26:53 +0000 Subject: [PATCH] Add support for implicit TLS model used with MS VC runtime. Patch by Kai Nacke! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@150307 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCExpr.h | 1 + include/llvm/MC/MCObjectFileInfo.h | 2 +- lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 11 +++- lib/MC/MCExpr.cpp | 1 + lib/MC/MCObjectFileInfo.cpp | 6 ++ lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 8 ++- .../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 6 ++ .../MCTargetDesc/X86WinCOFFObjectWriter.cpp | 2 +- lib/Target/X86/X86AsmPrinter.cpp | 1 + lib/Target/X86/X86ISelLowering.cpp | 62 +++++++++++++++++++ lib/Target/X86/X86MCInstLower.cpp | 4 +- test/CodeGen/X86/tls1.ll | 16 +++-- test/CodeGen/X86/tls11.ll | 17 +++-- test/CodeGen/X86/tls12.ll | 17 +++-- test/CodeGen/X86/tls13.ll | 21 +++++-- test/CodeGen/X86/tls14.ll | 21 +++++-- test/CodeGen/X86/tls2.ll | 20 ++++-- test/CodeGen/X86/tls3.ll | 19 ++++-- test/CodeGen/X86/tls4.ll | 20 ++++-- test/CodeGen/X86/tls5.ll | 15 +++-- test/CodeGen/X86/tls6.ll | 20 ++++-- 21 files changed, 233 insertions(+), 57 deletions(-) diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 093278395f6..2ae1e848382 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -162,6 +162,7 @@ public: VK_TPOFF, VK_DTPOFF, VK_TLVP, // Mach-O thread local variable relocation + VK_SECREL, // FIXME: We'd really like to use the generic Kinds listed above for these. VK_ARM_PLT, // ARM-style PLT references. i.e., (PLT) instead of @PLT VK_ARM_TLSGD, // ditto for TLSGD, GOT, GOTOFF, TPOFF and GOTTPOFF diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index c3d2019f37c..e58e7d68f7f 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -109,7 +109,7 @@ protected: const MCSection *TLSExtraDataSection; /// TLSDataSection - Section directive for Thread Local data. - /// ELF and MachO only. + /// ELF, MachO and COFF. const MCSection *TLSDataSection; // Defaults to ".tdata". /// TLSBSSSection - Section directive for Thread Local uninitialized data. diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index fd67d628b65..3a71f4f1267 100644 --- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -588,6 +588,11 @@ getCOFFSectionFlags(SectionKind K) { COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE; + else if (K.isThreadLocal()) + Flags |= + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE; else if (K.isReadOnly()) Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | @@ -614,6 +619,8 @@ static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) { return ".text$"; if (Kind.isBSS ()) return ".bss$"; + if (Kind.isThreadLocal()) + return ".tls$"; if (Kind.isWriteable()) return ".data$"; return ".rdata$"; @@ -623,7 +630,6 @@ static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) { const MCSection *TargetLoweringObjectFileCOFF:: SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { - assert(!Kind.isThreadLocal() && "Doesn't support TLS"); // If this global is linkonce/weak and the target handles this by emitting it // into a 'uniqued' section name, create and return the section now. @@ -644,6 +650,9 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, if (Kind.isText()) return getTextSection(); + if (Kind.isThreadLocal()) + return getTLSDataSection(); + return getDataSection(); } diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index ccdccdf5146..f3a91cbd5ef 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -188,6 +188,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_TPOFF: return "TPOFF"; case VK_DTPOFF: return "DTPOFF"; case VK_TLVP: return "TLVP"; + case VK_SECREL: return "SECREL"; case VK_ARM_PLT: return "(PLT)"; case VK_ARM_GOT: return "(GOT)"; case VK_ARM_GOTOFF: return "(GOTOFF)"; diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index 4c03aaa8732..1b8653531e8 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -495,6 +495,12 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE, SectionKind::getDataRel()); + TLSDataSection = + Ctx->getCOFFSection(".tls$", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); } void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm, diff --git a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h index 820b248909b..c41e9e7aef6 100644 --- a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h +++ b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h @@ -164,7 +164,13 @@ namespace X86II { /// is some TLS offset from the picbase. /// /// This is the 32-bit TLS offset for Darwin TLS in PIC mode. - MO_TLVP_PIC_BASE + MO_TLVP_PIC_BASE, + + /// MO_SECREL - On a symbol operand this indicates that the immediate is + /// the offset from beginning of section. + /// + /// This is the TLS offset for the COFF/Windows TLS mechanism. + MO_SECREL }; enum { diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 7f24766f678..b0305b44cff 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -222,6 +222,7 @@ EmitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size, // If we have an immoffset, add it to the expression. if ((FixupKind == FK_Data_4 || + FixupKind == FK_Data_8 || FixupKind == MCFixupKind(X86::reloc_signed_4byte))) { GlobalOffsetTableExprKind Kind = StartsWithGlobalOffsetTable(Expr); if (Kind != GOT_None) { @@ -230,6 +231,11 @@ EmitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size, FixupKind = MCFixupKind(X86::reloc_global_offset_table); if (Kind == GOT_Normal) ImmOffset = CurByte; + } else if (Expr->getKind() == MCExpr::SymbolRef) { + const MCSymbolRefExpr *Ref = static_cast(Expr); + if (Ref->getKind() == MCSymbolRefExpr::VK_SECREL) { + FixupKind = MCFixupKind(FK_SecRel_4); + } } } diff --git a/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp index a337aaa6a52..bc272efcc9c 100644 --- a/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp @@ -52,7 +52,7 @@ unsigned X86WinCOFFObjectWriter::getRelocType(unsigned FixupKind) const { return COFF::IMAGE_REL_AMD64_ADDR64; llvm_unreachable("unsupported relocation type"); case FK_SecRel_4: - return Is64Bit ? COFF::IMAGE_REL_AMD64_SREL32 : COFF::IMAGE_REL_I386_SECREL; + return Is64Bit ? COFF::IMAGE_REL_AMD64_SECREL : COFF::IMAGE_REL_I386_SECREL; default: llvm_unreachable("unsupported relocation type"); } diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index 5949064ee38..c61ad729d98 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -199,6 +199,7 @@ void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO, case X86II::MO_TLVP_PIC_BASE: O << "@TLVP" << '-' << *MF->getPICBaseSymbol(); break; + case X86II::MO_SECREL: O << "@SECREL"; break; } } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 1343b571ece..6d292068bd2 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -7355,6 +7355,68 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const { unsigned Reg = Subtarget->is64Bit() ? X86::RAX : X86::EAX; return DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy(), Chain.getValue(1)); + } else if (Subtarget->isTargetWindows()) { + // Just use the implicit TLS architecture + // Need to generate someting similar to: + // mov rdx, qword [gs:abs 58H]; Load pointer to ThreadLocalStorage + // ; from TEB + // mov ecx, dword [rel _tls_index]: Load index (from C runtime) + // mov rcx, qword [rdx+rcx*8] + // mov eax, .tls$:tlsvar + // [rax+rcx] contains the address + // Windows 64bit: gs:0x58 + // Windows 32bit: fs:__tls_array + + // If GV is an alias then use the aliasee for determining + // thread-localness. + if (const GlobalAlias *GA = dyn_cast(GV)) + GV = GA->resolveAliasedGlobal(false); + DebugLoc dl = GA->getDebugLoc(); + SDValue Chain = DAG.getEntryNode(); + + // Get the Thread Pointer, which is %fs:__tls_array (32-bit) or + // %gs:0x58 (64-bit). + Value *Ptr = Constant::getNullValue(Subtarget->is64Bit() + ? Type::getInt8PtrTy(*DAG.getContext(), + 256) + : Type::getInt32PtrTy(*DAG.getContext(), + 257)); + + SDValue ThreadPointer = DAG.getLoad(getPointerTy(), dl, Chain, + Subtarget->is64Bit() + ? DAG.getIntPtrConstant(0x58) + : DAG.getExternalSymbol("_tls_array", + getPointerTy()), + MachinePointerInfo(Ptr), + false, false, false, 0); + + // Load the _tls_index variable + SDValue IDX = DAG.getExternalSymbol("_tls_index", getPointerTy()); + if (Subtarget->is64Bit()) + IDX = DAG.getExtLoad(ISD::ZEXTLOAD, dl, getPointerTy(), Chain, + IDX, MachinePointerInfo(), MVT::i32, + false, false, 0); + else + IDX = DAG.getLoad(getPointerTy(), dl, Chain, IDX, MachinePointerInfo(), + false, false, false, 0); + + SDValue Scale = DAG.getConstant(Log2_64_Ceil(TD->getPointerSize()), + getPointerTy()); + IDX = DAG.getNode(ISD::SHL, dl, getPointerTy(), IDX, Scale); + + SDValue res = DAG.getNode(ISD::ADD, dl, getPointerTy(), ThreadPointer, IDX); + res = DAG.getLoad(getPointerTy(), dl, Chain, res, MachinePointerInfo(), + false, false, false, 0); + + // Get the offset of start of .tls section + SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, + GA->getValueType(0), + GA->getOffset(), X86II::MO_SECREL); + SDValue Offset = DAG.getNode(X86ISD::Wrapper, dl, getPointerTy(), TGA); + + // The address of the thread local variable is the add of the thread + // pointer with the offset of the variable. + return DAG.getNode(ISD::ADD, dl, getPointerTy(), res, Offset); } llvm_unreachable("TLS not implemented for this target."); diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp index 89e19674486..c2c46986d2f 100644 --- a/lib/Target/X86/X86MCInstLower.cpp +++ b/lib/Target/X86/X86MCInstLower.cpp @@ -154,6 +154,7 @@ MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO, Ctx), Ctx); break; + case X86II::MO_SECREL: RefKind = MCSymbolRefExpr::VK_SECREL; break; case X86II::MO_TLSGD: RefKind = MCSymbolRefExpr::VK_TLSGD; break; case X86II::MO_GOTTPOFF: RefKind = MCSymbolRefExpr::VK_GOTTPOFF; break; case X86II::MO_INDNTPOFF: RefKind = MCSymbolRefExpr::VK_INDNTPOFF; break; @@ -230,7 +231,8 @@ static void LowerUnaryToTwoAddr(MCInst &OutMI, unsigned NewOpc) { /// a short fixed-register form. static void SimplifyShortImmForm(MCInst &Inst, unsigned Opcode) { unsigned ImmOp = Inst.getNumOperands() - 1; - assert(Inst.getOperand(0).isReg() && Inst.getOperand(ImmOp).isImm() && + assert(Inst.getOperand(0).isReg() && + (Inst.getOperand(ImmOp).isImm() || Inst.getOperand(ImmOp).isExpr()) && ((Inst.getNumOperands() == 3 && Inst.getOperand(1).isReg() && Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) || Inst.getNumOperands() == 2) && "Unexpected instruction!"); diff --git a/test/CodeGen/X86/tls1.ll b/test/CodeGen/X86/tls1.ll index 0cae5c4f288..f39658e01b2 100644 --- a/test/CodeGen/X86/tls1.ll +++ b/test/CodeGen/X86/tls1.ll @@ -1,7 +1,7 @@ -; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t -; RUN: grep {movl %gs:i@NTPOFF, %eax} %t -; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2 -; RUN: grep {movl %fs:i@TPOFF, %eax} %t2 +; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s +; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s @i = thread_local global i32 15 @@ -10,3 +10,11 @@ entry: %tmp1 = load i32* @i ret i32 %tmp1 } +; X32_LINUX: movl %gs:i@NTPOFF, %eax +; X64_LINUX: movl %fs:i@TPOFF, %eax +; X32_WIN: movl __tls_index, %eax +; X32_WIN: movl %fs:__tls_array, %ecx +; X32_WIN: movl _i@SECREL(%eax), %eax +; X64_WIN: movl _tls_index(%rip), %eax +; X64_WIN: movabsq $i@SECREL, %rcx + diff --git a/test/CodeGen/X86/tls11.ll b/test/CodeGen/X86/tls11.ll index 514a168c538..cc148260370 100644 --- a/test/CodeGen/X86/tls11.ll +++ b/test/CodeGen/X86/tls11.ll @@ -1,7 +1,7 @@ -; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t -; RUN: grep {movzwl %gs:i@NTPOFF, %eax} %t -; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2 -; RUN: grep {movzwl %fs:i@TPOFF, %eax} %t2 +; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s +; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s @i = thread_local global i16 15 @@ -10,3 +10,12 @@ entry: %tmp1 = load i16* @i ret i16 %tmp1 } +; X32_LINUX: movzwl %gs:i@NTPOFF, %eax +; X64_LINUX: movzwl %fs:i@TPOFF, %eax +; X32_WIN: movl __tls_index, %eax +; X32_WIN: movl %fs:__tls_array, %ecx +; X32_WIN: movzwl _i@SECREL(%eax), %eax +; X64_WIN: movl _tls_index(%rip), %eax +; X64_WIN: movq %gs:88, %rcx +; X64_WIN: movabsq $i@SECREL, %rcx +; X64_WIN: movzwl (%rax,%rcx), %eax diff --git a/test/CodeGen/X86/tls12.ll b/test/CodeGen/X86/tls12.ll index c29f6adacd2..3da789e8f19 100644 --- a/test/CodeGen/X86/tls12.ll +++ b/test/CodeGen/X86/tls12.ll @@ -1,7 +1,7 @@ -; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t -; RUN: grep {movb %gs:i@NTPOFF, %al} %t -; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2 -; RUN: grep {movb %fs:i@TPOFF, %al} %t2 +; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s +; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s @i = thread_local global i8 15 @@ -10,3 +10,12 @@ entry: %tmp1 = load i8* @i ret i8 %tmp1 } +; X32_LINUX: movb %gs:i@NTPOFF, %al +; X64_LINUX: movb %fs:i@TPOFF, %al +; X32_WIN: movl __tls_index, %eax +; X32_WIN: movl %fs:__tls_array, %ecx +; X32_WIN: movb _i@SECREL(%eax), %al +; X64_WIN: movl _tls_index(%rip), %eax +; X64_WIN: movq %gs:88, %rcx +; X64_WIN: movabsq $i@SECREL, %rcx +; X64_WIN: movb (%rax,%rcx), %al diff --git a/test/CodeGen/X86/tls13.ll b/test/CodeGen/X86/tls13.ll index 08778ec2ce8..0f6a98a0665 100644 --- a/test/CodeGen/X86/tls13.ll +++ b/test/CodeGen/X86/tls13.ll @@ -1,9 +1,7 @@ -; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t -; RUN: grep {movswl %gs:i@NTPOFF, %eax} %t -; RUN: grep {movzwl %gs:j@NTPOFF, %eax} %t -; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2 -; RUN: grep {movswl %fs:i@TPOFF, %edi} %t2 -; RUN: grep {movzwl %fs:j@TPOFF, %edi} %t2 +; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s +; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s @i = thread_local global i16 0 @j = thread_local global i16 0 @@ -22,3 +20,14 @@ entry: declare void @g(i32) declare void @h(i32) + +; X32_LINUX: movswl %gs:i@NTPOFF, %eax +; X32_LINUX: movzwl %gs:j@NTPOFF, %eax +; X64_LINUX: movswl %fs:i@TPOFF, %edi +; X64_LINUX: movzwl %fs:j@TPOFF, %edi +; X32_WIN: movswl _i@SECREL(%esi), %eax +; X32_WIN: movzwl _j@SECREL(%esi), %eax +; X64_WIN: movabsq $i@SECREL, %rax +; X64_WIN: movswl (%rsi,%rax), %ecx +; X64_WIN: movabsq $j@SECREL, %rax +; X64_WIN: movzwl (%rsi,%rax), %ecx diff --git a/test/CodeGen/X86/tls14.ll b/test/CodeGen/X86/tls14.ll index 88426dd43d5..64625718410 100644 --- a/test/CodeGen/X86/tls14.ll +++ b/test/CodeGen/X86/tls14.ll @@ -1,9 +1,7 @@ -; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t -; RUN: grep {movsbl %gs:i@NTPOFF, %eax} %t -; RUN: grep {movzbl %gs:j@NTPOFF, %eax} %t -; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2 -; RUN: grep {movsbl %fs:i@TPOFF, %edi} %t2 -; RUN: grep {movzbl %fs:j@TPOFF, %edi} %t2 +; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s +; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s @i = thread_local global i8 0 @j = thread_local global i8 0 @@ -22,3 +20,14 @@ entry: declare void @g(i32) declare void @h(i32) + +; X32_LINUX: movsbl %gs:i@NTPOFF, %eax +; X32_LINUX: movzbl %gs:j@NTPOFF, %eax +; X64_LINUX: movsbl %fs:i@TPOFF, %edi +; X64_LINUX: movzbl %fs:j@TPOFF, %edi +; X32_WIN: movsbl _i@SECREL(%esi), %eax +; X32_WIN: movzbl _j@SECREL(%esi), %eax +; X64_WIN: movabsq $i@SECREL, %rax +; X64_WIN: movsbl (%rsi,%rax), %ecx +; X64_WIN: movabsq $j@SECREL, %rax +; X64_WIN: movzbl (%rsi,%rax), %ecx diff --git a/test/CodeGen/X86/tls2.ll b/test/CodeGen/X86/tls2.ll index 5a94296afef..e882f535ffb 100644 --- a/test/CodeGen/X86/tls2.ll +++ b/test/CodeGen/X86/tls2.ll @@ -1,9 +1,7 @@ -; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t -; RUN: grep {movl %gs:0, %eax} %t -; RUN: grep {leal i@NTPOFF(%eax), %eax} %t -; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2 -; RUN: grep {movq %fs:0, %rax} %t2 -; RUN: grep {leaq i@TPOFF(%rax), %rax} %t2 +; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s +; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s @i = thread_local global i32 15 @@ -11,3 +9,13 @@ define i32* @f() { entry: ret i32* @i } +; X32_LINUX: movl %gs:0, %eax +; X32_LINUX: leal i@NTPOFF(%eax), %eax +; X64_LINUX: movq %fs:0, %rax +; X64_LINUX: leaq i@TPOFF(%rax), %rax +; X32_WIN: movl __tls_index, %eax +; X32_WIN: movl %fs:__tls_array, %ecx +; X32_WIN: leal _i@SECREL(%eax), %eax +; X64_WIN: movl _tls_index(%rip), %eax +; X64_WIN: movq %gs:88, %rcx +; X64_WIN: addq $i@SECREL, %rax diff --git a/test/CodeGen/X86/tls3.ll b/test/CodeGen/X86/tls3.ll index 7327cc41777..ee3f28f4daf 100644 --- a/test/CodeGen/X86/tls3.ll +++ b/test/CodeGen/X86/tls3.ll @@ -1,9 +1,7 @@ -; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t -; RUN: grep {movl i@INDNTPOFF, %eax} %t -; RUN: grep {movl %gs:(%eax), %eax} %t -; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2 -; RUN: grep {movq i@GOTTPOFF(%rip), %rax} %t2 -; RUN: grep {movl %fs:(%rax), %eax} %t2 +; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s +; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s @i = external thread_local global i32 ; [#uses=2] @@ -12,3 +10,12 @@ entry: %tmp1 = load i32* @i ; [#uses=1] ret i32 %tmp1 } +; X32_LINUX: movl i@INDNTPOFF, %eax +; X32_LINUX: movl %gs:(%eax), %eax +; X64_LINUX: movq i@GOTTPOFF(%rip), %rax +; X64_LINUX: movl %fs:(%rax), %eax +; X32_WIN: movl __tls_index, %eax +; X32_WIN: movl %fs:__tls_array, %ecx +; X32_WIN: movl _i@SECREL(%eax), %eax +; X64_WIN: movl _tls_index(%rip), %eax +; X64_WIN: movabsq $i@SECREL, %rcx diff --git a/test/CodeGen/X86/tls4.ll b/test/CodeGen/X86/tls4.ll index d2e40e389bd..2b53ec57fea 100644 --- a/test/CodeGen/X86/tls4.ll +++ b/test/CodeGen/X86/tls4.ll @@ -1,9 +1,7 @@ -; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t -; RUN: grep {movl %gs:0, %eax} %t -; RUN: grep {addl i@INDNTPOFF, %eax} %t -; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2 -; RUN: grep {movq %fs:0, %rax} %t2 -; RUN: grep {addq i@GOTTPOFF(%rip), %rax} %t2 +; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s +; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s @i = external thread_local global i32 ; [#uses=2] @@ -11,3 +9,13 @@ define i32* @f() { entry: ret i32* @i } +; X32_LINUX: movl %gs:0, %eax +; X32_LINUX: addl i@INDNTPOFF, %eax +; X64_LINUX: movq %fs:0, %rax +; X64_LINUX: addq i@GOTTPOFF(%rip), %rax +; X32_WIN: movl __tls_index, %eax +; X32_WIN: movl %fs:__tls_array, %ecx +; X32_WIN: leal _i@SECREL(%eax), %eax +; X64_WIN: movl _tls_index(%rip), %eax +; X64_WIN: movq %gs:88, %rcx +; X64_WIN: addq $i@SECREL, %rax diff --git a/test/CodeGen/X86/tls5.ll b/test/CodeGen/X86/tls5.ll index 4d2cc02b502..3cc6dab5904 100644 --- a/test/CodeGen/X86/tls5.ll +++ b/test/CodeGen/X86/tls5.ll @@ -1,7 +1,7 @@ -; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t -; RUN: grep {movl %gs:i@NTPOFF, %eax} %t -; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2 -; RUN: grep {movl %fs:i@TPOFF, %eax} %t2 +; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s +; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s @i = internal thread_local global i32 15 @@ -10,3 +10,10 @@ entry: %tmp1 = load i32* @i ret i32 %tmp1 } +; X32_LINUX: movl %gs:i@NTPOFF, %eax +; X64_LINUX: movl %fs:i@TPOFF, %eax +; X32_WIN: movl __tls_index, %eax +; X32_WIN: movl %fs:__tls_array, %ecx +; X32_WIN: movl _i@SECREL(%eax), %eax +; X64_WIN: movl _tls_index(%rip), %eax +; X64_WIN: movabsq $i@SECREL, %rcx diff --git a/test/CodeGen/X86/tls6.ll b/test/CodeGen/X86/tls6.ll index 505106ee14e..c98ad7c360e 100644 --- a/test/CodeGen/X86/tls6.ll +++ b/test/CodeGen/X86/tls6.ll @@ -1,9 +1,7 @@ -; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t -; RUN: grep {movl %gs:0, %eax} %t -; RUN: grep {leal i@NTPOFF(%eax), %eax} %t -; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2 -; RUN: grep {movq %fs:0, %rax} %t2 -; RUN: grep {leaq i@TPOFF(%rax), %rax} %t2 +; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s +; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s @i = internal thread_local global i32 15 @@ -11,3 +9,13 @@ define i32* @f() { entry: ret i32* @i } +; X32_LINUX: movl %gs:0, %eax +; X32_LINUX: leal i@NTPOFF(%eax), %eax +; X64_LINUX: movq %fs:0, %rax +; X64_LINUX: leaq i@TPOFF(%rax), %rax +; X32_WIN: movl __tls_index, %eax +; X32_WIN: movl %fs:__tls_array, %ecx +; X32_WIN: leal _i@SECREL(%eax), %eax +; X64_WIN: movl _tls_index(%rip), %eax +; X64_WIN: movq %gs:88, %rcx +; X64_WIN: addq $i@SECREL, %rax -- 2.34.1