diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 40359c49fc2..e7f5b6a7d5f 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -184,6 +184,9 @@ public: VK_Mips_ABS_HI, VK_Mips_ABS_LO, VK_Mips_TLSGD, + VK_Mips_TLSLDM, + VK_Mips_DTPREL_HI, + VK_Mips_DTPREL_LO, VK_Mips_GOTTPREL, VK_Mips_TPREL_HI, VK_Mips_TPREL_LO, diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index 469e73382f5..3e9c46a4614 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -101,6 +101,9 @@ static void printExpr(const MCExpr *Expr, raw_ostream &OS) { case MCSymbolRefExpr::VK_Mips_ABS_HI: OS << "%hi("; break; case MCSymbolRefExpr::VK_Mips_ABS_LO: OS << "%lo("; break; case MCSymbolRefExpr::VK_Mips_TLSGD: OS << "%tlsgd("; break; + case MCSymbolRefExpr::VK_Mips_TLSLDM: OS << "%tlsldm("; break; + case MCSymbolRefExpr::VK_Mips_DTPREL_HI:OS << "%dtprel_hi("; break; + case MCSymbolRefExpr::VK_Mips_DTPREL_LO:OS << "%dtprel_lo("; break; case MCSymbolRefExpr::VK_Mips_GOTTPREL: OS << "%gottprel("; break; case MCSymbolRefExpr::VK_Mips_TPREL_HI: OS << "%tprel_hi("; break; case MCSymbolRefExpr::VK_Mips_TPREL_LO: OS << "%tprel_lo("; break; diff --git a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index be2815db051..00fc5dfb356 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -56,6 +56,13 @@ namespace MipsII { // Dynamic TLS). MO_TLSGD, + /// MO_TLSLDM - Represents the offset into the global offset table at which + // the module ID and TSL block offset reside during execution (Local + // Dynamic TLS). + MO_TLSLDM, + MO_DTPREL_HI, + MO_DTPREL_LO, + /// MO_GOTTPREL - Represents the offset from the thread pointer (Initial // Exec TLS). MO_GOTTPREL, diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 5da9a10fd4f..c9b657c654b 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -1540,9 +1540,9 @@ SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op, SDValue MipsTargetLowering:: LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const { - // If the relocation model is PIC, use the General Dynamic TLS Model, - // otherwise use the Initial Exec or Local Exec TLS Model. - // TODO: implement Local Dynamic TLS model + // If the relocation model is PIC, use the General Dynamic TLS Model or + // Local Dynamic TLS model, otherwise use the Initial Exec or + // Local Exec TLS Model. GlobalAddressSDNode *GA = cast(Op); DebugLoc dl = GA->getDebugLoc(); @@ -1551,8 +1551,9 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { // General Dynamic TLS Model - SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, - 0, MipsII::MO_TLSGD); + bool LocalDynamic = GV->hasInternalLinkage(); + unsigned Flag = LocalDynamic ? MipsII::MO_TLSLDM :MipsII::MO_TLSGD; + SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, Flag); SDValue Argument = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, TGA); unsigned PtrSize = PtrVT.getSizeInBits(); IntegerType *PtrTy = Type::getIntNTy(*DAG.getContext(), PtrSize); @@ -1570,7 +1571,19 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const false, false, false, false, 0, CallingConv::C, false, true, TlsGetAddr, Args, DAG, dl); - return CallResult.first; + SDValue Ret = CallResult.first; + + if (!LocalDynamic) + return Ret; + + SDValue TGAHi = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, + MipsII::MO_DTPREL_HI); + SDValue Hi = DAG.getNode(MipsISD::Hi, dl, PtrVT, TGAHi); + SDValue TGALo = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, + MipsII::MO_DTPREL_LO); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, PtrVT, TGALo); + SDValue Add = DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Ret); + return DAG.getNode(ISD::ADD, dl, PtrVT, Add, Lo); } SDValue Offset; diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp index de65881b794..23486d3d33b 100644 --- a/lib/Target/Mips/MipsMCInstLower.cpp +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -46,6 +46,9 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, case MipsII::MO_ABS_HI: Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break; case MipsII::MO_ABS_LO: Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break; case MipsII::MO_TLSGD: Kind = MCSymbolRefExpr::VK_Mips_TLSGD; break; + case MipsII::MO_TLSLDM: Kind = MCSymbolRefExpr::VK_Mips_TLSLDM; break; + case MipsII::MO_DTPREL_HI:Kind = MCSymbolRefExpr::VK_Mips_DTPREL_HI; break; + case MipsII::MO_DTPREL_LO:Kind = MCSymbolRefExpr::VK_Mips_DTPREL_LO; break; case MipsII::MO_GOTTPREL: Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break; case MipsII::MO_TPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break; case MipsII::MO_TPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break; diff --git a/test/CodeGen/Mips/tls.ll b/test/CodeGen/Mips/tls.ll index b0474b4c443..3fa852b454c 100644 --- a/test/CodeGen/Mips/tls.ll +++ b/test/CodeGen/Mips/tls.ll @@ -44,3 +44,22 @@ entry: ; STATIC: addu $[[R1:[0-9]+]], $3, $[[R0]] ; STATIC: lw $2, 0($[[R1]]) } + +@f3.i = internal thread_local unnamed_addr global i32 1, align 4 + +define i32 @f3() nounwind { +entry: +; CHECK: f3: + +; PIC: addiu $4, $gp, %tlsldm(f3.i) +; PIC: jalr $25 +; PIC: lui $[[R0:[0-9]+]], %dtprel_hi(f3.i) +; PIC: addu $[[R1:[0-9]+]], $[[R0]], $2 +; PIC: addiu ${{[0-9]+}}, $[[R1]], %dtprel_lo(f3.i) + + %0 = load i32* @f3.i, align 4 + %inc = add nsw i32 %0, 1 + store i32 %inc, i32* @f3.i, align 4 + ret i32 %inc +} +