Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -1172,6 +1172,11 @@ def : MipsPat<(MipsGotHi texternalsym:$in), (LUi_MM texternalsym:$in)>, ISA_MICROMIPS; +def : MipsPat<(MipsDtprelHi tglobaltlsaddr:$in), (LUi_MM tglobaltlsaddr:$in)>, + ISA_MICROMIPS; +def : MipsPat<(MipsTprelHi tglobaltlsaddr:$in), (LUi_MM tglobaltlsaddr:$in)>, + ISA_MICROMIPS; + // gp_rel relocs def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)), (ADDiu_MM GPR32:$gp, tglobaladdr:$in)>, ISA_MICROMIPS; Index: lib/Target/Mips/Mips16InstrInfo.td =================================================================== --- lib/Target/Mips/Mips16InstrInfo.td +++ lib/Target/Mips/Mips16InstrInfo.td @@ -1858,11 +1858,14 @@ (SllX16 (LiRxImmX16 tglobaladdr:$in), 16)>; def : Mips16Pat<(MipsHi tjumptable:$in), (SllX16 (LiRxImmX16 tjumptable:$in), 16)>; -def : Mips16Pat<(MipsHi tglobaltlsaddr:$in), - (SllX16 (LiRxImmX16 tglobaltlsaddr:$in), 16)>; def : Mips16Pat<(MipsLo tblockaddress:$in), (LiRxImmX16 tblockaddress:$in)>; +def : Mips16Pat<(MipsDtprelHi tglobaltlsaddr:$in), + (SllX16 (LiRxImmX16 tglobaltlsaddr:$in), 16)>; +def : Mips16Pat<(MipsTprelHi tglobaltlsaddr:$in), + (SllX16 (LiRxImmX16 tglobaltlsaddr:$in), 16)>; + // wrapper_pic class Wrapper16Pat: Mips16Pat<(MipsWrapper RC:$gp, node:$in), Index: lib/Target/Mips/Mips64InstrInfo.td =================================================================== --- lib/Target/Mips/Mips64InstrInfo.td +++ lib/Target/Mips/Mips64InstrInfo.td @@ -611,6 +611,9 @@ def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>; def : MipsPat<(MipsGotHi texternalsym:$in), (LUi64 texternalsym:$in)>; +def : MipsPat<(MipsTprelHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>; +def : MipsPat<(MipsDtprelHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>; + // highest/higher/hi/lo relocs let AdditionalPredicates = [NotInMicroMips] in { def : MipsPat<(MipsJmpLink (i64 texternalsym:$dst)), @@ -623,8 +626,6 @@ (LUi64 tjumptable:$in)>, SYM_64; def : MipsPat<(MipsHighest (i64 tconstpool:$in)), (LUi64 tconstpool:$in)>, SYM_64; - def : MipsPat<(MipsHighest (i64 tglobaltlsaddr:$in)), - (LUi64 tglobaltlsaddr:$in)>, SYM_64; def : MipsPat<(MipsHighest (i64 texternalsym:$in)), (LUi64 texternalsym:$in)>, SYM_64; @@ -636,8 +637,6 @@ (DADDiu ZERO_64, tjumptable:$in)>, SYM_64; def : MipsPat<(MipsHigher (i64 tconstpool:$in)), (DADDiu ZERO_64, tconstpool:$in)>, SYM_64; - def : MipsPat<(MipsHigher (i64 tglobaltlsaddr:$in)), - (DADDiu ZERO_64, tglobaltlsaddr:$in)>, SYM_64; def : MipsPat<(MipsHigher (i64 texternalsym:$in)), (DADDiu ZERO_64, texternalsym:$in)>, SYM_64; @@ -649,8 +648,6 @@ (DADDiu GPR64:$hi, tjumptable:$lo)>, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tconstpool:$lo))), (DADDiu GPR64:$hi, tconstpool:$lo)>, SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tglobaltlsaddr:$lo))), - (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaladdr:$lo))), (DADDiu GPR64:$hi, tglobaladdr:$lo)>, SYM_64; @@ -660,8 +657,6 @@ (DADDiu GPR64:$hi, tjumptable:$lo)>, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tconstpool:$lo))), (DADDiu GPR64:$hi, tconstpool:$lo)>, SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaltlsaddr:$lo))), - (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaladdr:$lo))), (DADDiu GPR64:$hi, tglobaladdr:$lo)>, SYM_64; Index: lib/Target/Mips/MipsISelLowering.h =================================================================== --- lib/Target/Mips/MipsISelLowering.h +++ lib/Target/Mips/MipsISelLowering.h @@ -84,6 +84,12 @@ // Get the High 16 bits from a 32 bit immediate for accessing the GOT. GotHi, + // Get the High 16 bits from a 32-bit immediate for accessing the DTP. + DtprelHi, + + // Get the High 16 bits from a 32-bit immediate for accessing the TP. + TprelHi, + // Handle gp_rel (small data/bss sections) relocation. GPRel, Index: lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsISelLowering.cpp +++ lib/Target/Mips/MipsISelLowering.cpp @@ -189,6 +189,8 @@ case MipsISD::Hi: return "MipsISD::Hi"; case MipsISD::Lo: return "MipsISD::Lo"; case MipsISD::GotHi: return "MipsISD::GotHi"; + case MipsISD::DtprelHi: return "MipsISD::DtprelHi"; + case MipsISD::TprelHi: return "MipsISD::TprelHi"; case MipsISD::GPRel: return "MipsISD::GPRel"; case MipsISD::ThreadPointer: return "MipsISD::ThreadPointer"; case MipsISD::Ret: return "MipsISD::Ret"; @@ -2093,7 +2095,7 @@ SDValue TGAHi = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, MipsII::MO_DTPREL_HI); - SDValue Hi = DAG.getNode(MipsISD::Hi, DL, PtrVT, TGAHi); + SDValue Hi = DAG.getNode(MipsISD::DtprelHi, DL, PtrVT, TGAHi); SDValue TGALo = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, MipsII::MO_DTPREL_LO); SDValue Lo = DAG.getNode(MipsISD::Lo, DL, PtrVT, TGALo); @@ -2117,7 +2119,7 @@ MipsII::MO_TPREL_HI); SDValue TGALo = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, MipsII::MO_TPREL_LO); - SDValue Hi = DAG.getNode(MipsISD::Hi, DL, PtrVT, TGAHi); + SDValue Hi = DAG.getNode(MipsISD::TprelHi, DL, PtrVT, TGAHi); SDValue Lo = DAG.getNode(MipsISD::Lo, DL, PtrVT, TGALo); Offset = DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Lo); } Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -73,12 +73,9 @@ // Hi node for accessing the GOT. def MipsGotHi : SDNode<"MipsISD::GotHi", SDTIntUnaryOp>; -// TlsGd node is used to handle General Dynamic TLS -def MipsTlsGd : SDNode<"MipsISD::TlsGd", SDTIntUnaryOp>; - -// TprelHi and TprelLo nodes are used to handle Local Exec TLS +// DtprelHi and TprelHi nodes used to handle Local Dynamic and Local Exec TLS +def MipsDtprelHi : SDNode<"MipsISD::DtprelHi", SDTIntUnaryOp>; def MipsTprelHi : SDNode<"MipsISD::TprelHi", SDTIntUnaryOp>; -def MipsTprelLo : SDNode<"MipsISD::TprelLo", SDTIntUnaryOp>; // Thread pointer def MipsThreadPointer: SDNode<"MipsISD::ThreadPointer", SDT_MipsThreadPointer>; @@ -2992,7 +2989,6 @@ def : MipsPat<(MipsHi tblockaddress:$in), (Lui tblockaddress:$in)>; def : MipsPat<(MipsHi tjumptable:$in), (Lui tjumptable:$in)>; def : MipsPat<(MipsHi tconstpool:$in), (Lui tconstpool:$in)>; - def : MipsPat<(MipsHi tglobaltlsaddr:$in), (Lui tglobaltlsaddr:$in)>; def : MipsPat<(MipsHi texternalsym:$in), (Lui texternalsym:$in)>; def : MipsPat<(MipsLo tglobaladdr:$in), (Addiu ZeroReg, tglobaladdr:$in)>; @@ -3023,6 +3019,11 @@ def : MipsPat<(MipsGotHi texternalsym:$in), (LUi texternalsym:$in)>, ISA_MIPS1; + def : MipsPat<(MipsDtprelHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>, + ISA_MIPS1; + def : MipsPat<(MipsTprelHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>, + ISA_MIPS1; + // gp_rel relocs def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)), (ADDiu GPR32:$gp, tglobaladdr:$in)>, ISA_MIPS1, ABI_NOT_N64; Index: test/CodeGen/Mips/tls.ll =================================================================== --- test/CodeGen/Mips/tls.ll +++ test/CodeGen/Mips/tls.ll @@ -1,10 +1,17 @@ ; RUN: llc -mtriple=mipsel-- -disable-mips-delay-filler -relocation-model=pic < %s | \ -; RUN: FileCheck %s -check-prefixes=PIC,CHECK +; RUN: FileCheck %s -check-prefixes=PIC32,CHECK +; RUN: llc -mtriple=mips64el-- -disable-mips-delay-filler -relocation-model=pic < %s | \ +; RUN: FileCheck %s -check-prefixes=PIC64,CHECK ; RUN: llc -mtriple=mipsel-- -relocation-model=static -disable-mips-delay-filler < \ -; RUN: %s | FileCheck %s -check-prefixes=STATIC,CHECK +; RUN: %s | FileCheck %s -check-prefixes=STATIC32,CHECK +; RUN: llc -mtriple=mips64el-- -relocation-model=static -disable-mips-delay-filler < \ +; RUN: %s | FileCheck %s -check-prefixes=STATIC64,CHECK ; RUN: llc -mtriple=mipsel-- -relocation-model=static -disable-mips-delay-filler \ ; RUN: -mips-fix-global-base-reg=false < %s | \ -; RUN: FileCheck %s -check-prefixes=STATICGP,CHECK +; RUN: FileCheck %s -check-prefixes=STATICGP32,CHECK +; RUN: llc -mtriple=mips64el-- -relocation-model=static -disable-mips-delay-filler \ +; RUN: -mips-fix-global-base-reg=false < %s | \ +; RUN: FileCheck %s -check-prefixes=STATICGP64,CHECK @t1 = thread_local global i32 0, align 4 @@ -13,19 +20,33 @@ %tmp = load i32, i32* @t1, align 4 ret i32 %tmp -; PIC-LABEL: f1: -; PIC-DAG: addu $[[R0:[a-z0-9]+]], $2, $25 -; PIC-DAG: lw $25, %call16(__tls_get_addr)($[[R0]]) -; PIC-DAG: addiu $4, $[[R0]], %tlsgd(t1) -; PIC-DAG: jalr $25 -; PIC-DAG: lw $2, 0($2) - -; STATIC-LABEL: f1: -; STATIC: lui $[[R0:[0-9]+]], %tprel_hi(t1) -; STATIC: addiu $[[R1:[0-9]+]], $[[R0]], %tprel_lo(t1) -; STATIC: rdhwr $3, $29 -; STATIC: addu $[[R2:[0-9]+]], $3, $[[R1]] -; STATIC: lw $2, 0($[[R2]]) +; PIC32-LABEL: f1: +; PIC32-DAG: addu $[[R0:[a-z0-9]+]], $2, $25 +; PIC32-DAG: lw $25, %call16(__tls_get_addr)($[[R0]]) +; PIC32-DAG: addiu $4, $[[R0]], %tlsgd(t1) +; PIC32-DAG: jalr $25 +; PIC32-DAG: lw $2, 0($2) + +; PIC64-LABEL: f1: +; PIC64-DAG: daddiu $[[R0:[a-z0-9]+]], $1, %lo(%neg(%gp_rel(f1))) +; PIC64-DAG: ld $25, %call16(__tls_get_addr)($[[R0]]) +; PIC64-DAG: daddiu $4, $[[R0]], %tlsgd(t1) +; PIC64-DAG: jalr $25 +; PIC64-DAG: lw $2, 0($2) + +; STATIC32-LABEL: f1: +; STATIC32: lui $[[R0:[0-9]+]], %tprel_hi(t1) +; STATIC32: addiu $[[R1:[0-9]+]], $[[R0]], %tprel_lo(t1) +; STATIC32: rdhwr $3, $29 +; STATIC32: addu $[[R2:[0-9]+]], $3, $[[R1]] +; STATIC32: lw $2, 0($[[R2]]) + +; STATIC64-LABEL: f1: +; STATIC64: lui $[[R0:[0-9]+]], %tprel_hi(t1) +; STATIC64: daddiu $[[R1:[0-9]+]], $[[R0]], %tprel_lo(t1) +; STATIC64: rdhwr $3, $29 +; STATIC64: daddu $[[R2:[0-9]+]], $3, $[[R1]] +; STATIC64: lw $2, 0($[[R2]]) } @@ -36,25 +57,45 @@ %tmp = load i32, i32* @t2, align 4 ret i32 %tmp -; PIC-LABEL: f2: -; PIC-DAG: addu $[[R0:[a-z0-9]+]], $2, $25 -; PIC-DAG: lw $25, %call16(__tls_get_addr)($[[R0]]) -; PIC-DAG: addiu $4, $[[R0]], %tlsgd(t2) -; PIC-DAG: jalr $25 -; PIC-DAG: lw $2, 0($2) - -; STATICGP-LABEL: f2: -; STATICGP: lui $[[R0:[0-9]+]], %hi(__gnu_local_gp) -; STATICGP: addiu $[[GP:[0-9]+]], $[[R0]], %lo(__gnu_local_gp) -; STATICGP: lw ${{[0-9]+}}, %gottprel(t2)($[[GP]]) - -; STATIC-LABEL: f2: -; STATIC: lui $[[R0:[0-9]+]], %hi(__gnu_local_gp) -; STATIC: addiu $[[GP:[0-9]+]], $[[R0]], %lo(__gnu_local_gp) -; STATIC: rdhwr $3, $29 -; STATIC: lw $[[R0:[0-9]+]], %gottprel(t2)($[[GP]]) -; STATIC: addu $[[R1:[0-9]+]], $3, $[[R0]] -; STATIC: lw $2, 0($[[R1]]) +; PIC32-LABEL: f2: +; PIC32-DAG: addu $[[R0:[a-z0-9]+]], $2, $25 +; PIC32-DAG: lw $25, %call16(__tls_get_addr)($[[R0]]) +; PIC32-DAG: addiu $4, $[[R0]], %tlsgd(t2) +; PIC32-DAG: jalr $25 +; PIC32-DAG: lw $2, 0($2) + +; PIC64-LABEL: f2: +; PIC64-DAG: daddiu $[[R0:[a-z0-9]+]], $1, %lo(%neg(%gp_rel(f2))) +; PIC64-DAG: ld $25, %call16(__tls_get_addr)($[[R0]]) +; PIC64-DAG: daddiu $4, $[[R0]], %tlsgd(t2) +; PIC64-DAG: jalr $25 +; PIC64-DAG: lw $2, 0($2) + +; STATICGP32-LABEL: f2: +; STATICGP32: lui $[[R0:[0-9]+]], %hi(__gnu_local_gp) +; STATICGP32: addiu $[[GP:[0-9]+]], $[[R0]], %lo(__gnu_local_gp) +; STATICGP32: lw ${{[0-9]+}}, %gottprel(t2)($[[GP]]) + +; STATICGP64-LABEL: f2: +; STATICGP64: lui $[[R0:[0-9]+]], %hi(%neg(%gp_rel(f2))) +; STATICGP64: daddiu $[[GP:[0-9]+]], $[[R0]], %lo(%neg(%gp_rel(f2))) +; STATICGP64: ld ${{[0-9]+}}, %gottprel(t2)($[[GP]]) + +; STATIC32-LABEL: f2: +; STATIC32: lui $[[R0:[0-9]+]], %hi(__gnu_local_gp) +; STATIC32: addiu $[[GP:[0-9]+]], $[[R0]], %lo(__gnu_local_gp) +; STATIC32: rdhwr $3, $29 +; STATIC32: lw $[[R0:[0-9]+]], %gottprel(t2)($[[GP]]) +; STATIC32: addu $[[R1:[0-9]+]], $3, $[[R0]] +; STATIC32: lw $2, 0($[[R1]]) + +; STATIC64-LABEL: f2: +; STATIC64: lui $[[R0:[0-9]+]], %hi(%neg(%gp_rel(f2))) +; STATIC64: daddiu $[[GP:[0-9]+]], $[[R0]], %lo(%neg(%gp_rel(f2))) +; STATIC64: rdhwr $3, $29 +; STATIC64: ld $[[R0:[0-9]+]], %gottprel(t2)($[[GP]]) +; STATIC64: daddu $[[R1:[0-9]+]], $3, $[[R0]] +; STATIC64: lw $2, 0($[[R1]]) } @f3.i = internal thread_local unnamed_addr global i32 1, align 4 @@ -63,11 +104,17 @@ entry: ; CHECK-LABEL: f3: -; PIC: addiu $4, ${{[a-z0-9]+}}, %tlsldm(f3.i) -; PIC: jalr $25 -; PIC: lui $[[R0:[0-9]+]], %dtprel_hi(f3.i) -; PIC: addu $[[R1:[0-9]+]], $[[R0]], $2 -; PIC: lw ${{[0-9]+}}, %dtprel_lo(f3.i)($[[R1]]) +; PIC32: addiu $4, ${{[a-z0-9]+}}, %tlsldm(f3.i) +; PIC32: jalr $25 +; PIC32: lui $[[R0:[0-9]+]], %dtprel_hi(f3.i) +; PIC32: addu $[[R1:[0-9]+]], $[[R0]], $2 +; PIC32: lw ${{[0-9]+}}, %dtprel_lo(f3.i)($[[R1]]) + +; PIC64: daddiu $4, ${{[a-z0-9]+}}, %tlsldm(f3.i) +; PIC64: jalr $25 +; PIC64: lui $[[R0:[0-9]+]], %dtprel_hi(f3.i) +; PIC64: daddu $[[R1:[0-9]+]], $[[R0]], $2 +; PIC64: lw ${{[0-9]+}}, %dtprel_lo(f3.i)($[[R1]]) %0 = load i32, i32* @f3.i, align 4 %inc = add nsw i32 %0, 1