diff --git a/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp index c3842785f2b..90039adcb20 100644 --- a/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ b/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -911,6 +911,16 @@ bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB, MI.eraseFromParent(); return true; } + case AArch64::ADDlowTLS: + // Produce a plain ADD + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADDXri)) + .add(MI.getOperand(0)) + .add(MI.getOperand(1)) + .add(MI.getOperand(2)) + .addImm(0); + MI.eraseFromParent(); + return true; + case AArch64::MOVbaseTLS: { unsigned DstReg = MI.getOperand(0).getReg(); auto SysReg = AArch64SysReg::TPIDR_EL0; diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp index 4f0a7a2eaf0..c795a4411ad 100644 --- a/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3918,10 +3918,7 @@ AArch64TargetLowering::LowerELFGlobalTLSAddress(SDValue Op, DAG.getTargetConstant(0, DL, MVT::i32)), 0); SDValue TPWithOff = - SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, TPWithOff_lo, - LoVar, - DAG.getTargetConstant(0, DL, MVT::i32)), - 0); + DAG.getNode(AArch64ISD::ADDlow, DL, PtrVT, TPWithOff_lo, LoVar); return TPWithOff; } else if (Model == TLSModel::InitialExec) { TPOff = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, AArch64II::MO_TLS); @@ -3958,9 +3955,7 @@ AArch64TargetLowering::LowerELFGlobalTLSAddress(SDValue Op, TPOff = SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, TPOff, HiVar, DAG.getTargetConstant(0, DL, MVT::i32)), 0); - TPOff = SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, TPOff, LoVar, - DAG.getTargetConstant(0, DL, MVT::i32)), - 0); + TPOff = DAG.getNode(AArch64ISD::ADDlow, DL, PtrVT, TPOff, LoVar); } else if (Model == TLSModel::GeneralDynamic) { // The call needs a relocation too for linker relaxation. It doesn't make // sense to call it MO_PAGE or MO_PAGEOFF though so we need another copy of @@ -4031,9 +4026,7 @@ AArch64TargetLowering::LowerWindowsGlobalTLSAddress(SDValue Op, SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, TLS, TGAHi, DAG.getTargetConstant(0, DL, MVT::i32)), 0); - Addr = SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, Addr, TGALo, - DAG.getTargetConstant(0, DL, MVT::i32)), - 0); + Addr = DAG.getNode(AArch64ISD::ADDlow, DL, PtrVT, Addr, TGALo); return Addr; } diff --git a/lib/Target/AArch64/AArch64InstrInfo.td b/lib/Target/AArch64/AArch64InstrInfo.td index db2e9062b64..18d0f8d8f28 100644 --- a/lib/Target/AArch64/AArch64InstrInfo.td +++ b/lib/Target/AArch64/AArch64InstrInfo.td @@ -396,6 +396,15 @@ def MOVaddrEXT [(set GPR64:$dst, (AArch64addlow (AArch64adrp texternalsym:$hi), texternalsym:$low))]>, Sched<[WriteAdrAdr]>; +// Normally AArch64addlow either gets folded into a following ldr/str, +// or together with an adrp into MOVaddr above. For cases with TLS, it +// might appear without either of them, so allow lowering it into a plain +// add. +def ADDlowTLS + : Pseudo<(outs GPR64:$dst), (ins GPR64:$src, i64imm:$low), + [(set GPR64:$dst, (AArch64addlow GPR64:$src, + tglobaltlsaddr:$low))]>, + Sched<[WriteAdr]>; } // isReMaterializable, isCodeGenOnly diff --git a/test/CodeGen/AArch64/arm64-tls-execs.ll b/test/CodeGen/AArch64/arm64-tls-execs.ll index deced698881..fc636d171cf 100644 --- a/test/CodeGen/AArch64/arm64-tls-execs.ll +++ b/test/CodeGen/AArch64/arm64-tls-execs.ll @@ -40,11 +40,10 @@ define i32 @test_local_exec() { ; CHECK: mrs x[[R1:[0-9]+]], TPIDR_EL0 ; CHECK: add x[[R2:[0-9]+]], x[[R1]], :tprel_hi12:local_exec_var -; CHECK: add x[[R3:[0-9]+]], x[[R2]], :tprel_lo12_nc:local_exec_var -; CHECK: ldr w0, [x[[R3]]] +; CHECK: ldr w0, [x[[R2]], :tprel_lo12_nc:local_exec_var] ; CHECK-RELOC: R_AARCH64_TLSLE_ADD_TPREL_HI12 -; CHECK-RELOC: R_AARCH64_TLSLE_ADD_TPREL_LO12_NC +; CHECK-RELOC: R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC ret i32 %val } diff --git a/test/CodeGen/AArch64/win-tls.ll b/test/CodeGen/AArch64/win-tls.ll index f85c413a43c..ea49b99bbaa 100644 --- a/test/CodeGen/AArch64/win-tls.ll +++ b/test/CodeGen/AArch64/win-tls.ll @@ -35,10 +35,7 @@ define i64 @getVar64() { ; CHECK: ldr [[TLS:x[0-9]+]], {{\[}}[[TLS_POINTER]], x[[TLS_INDEX]], lsl #3] ; CHECK: add [[TLS]], [[TLS]], :secrel_hi12:tlsVar -; This add+ldr could also be folded into a single ldr with a :secrel_lo12: -; offset. -; CHECK: add [[TLS]], [[TLS]], :secrel_lo12:tlsVar -; CHECK: ldr w0, {{\[}}[[TLS]]{{\]}} +; CHECK: ldr w0, {{\[}}[[TLS]], :secrel_lo12:tlsVar{{\]}} ; CHECK-LABEL: getPtr ; CHECK: adrp [[TLS_INDEX_ADDR:x[0-9]+]], _tls_index @@ -56,17 +53,12 @@ define i64 @getVar64() { ; CHECK: ldr [[TLS:x[0-9]+]], {{\[}}[[TLS_POINTER]], x[[TLS_INDEX]], lsl #3] ; CHECK: add [[TLS]], [[TLS]], :secrel_hi12:tlsVar -; This add+ldr could also be folded into a single ldr with a :secrel_lo12: -; offset. -; CHECK: add [[TLS]], [[TLS]], :secrel_lo12:tlsVar -; CHECK: str w0, {{\[}}[[TLS]]{{\]}} +; CHECK: str w0, {{\[}}[[TLS]], :secrel_lo12:tlsVar{{\]}} ; CHECK-LABEL: getVar8 ; CHECK: add [[TLS:x[0-9]+]], [[TLS]], :secrel_hi12:tlsVar8 -; CHECK: add [[TLS]], [[TLS]], :secrel_lo12:tlsVar8 -; CHECK: ldrb w0, {{\[}}[[TLS]]{{\]}} +; CHECK: ldrb w0, {{\[}}[[TLS]], :secrel_lo12:tlsVar8{{\]}} ; CHECK-LABEL: getVar64 ; CHECK: add [[TLS:x[0-9]+]], [[TLS]], :secrel_hi12:tlsVar64 -; CHECK: add [[TLS]], [[TLS]], :secrel_lo12:tlsVar64 -; CHECK: ldr x0, {{\[}}[[TLS]]{{\]}} +; CHECK: ldr x0, {{\[}}[[TLS]], :secrel_lo12:tlsVar64{{\]}}