diff options
Diffstat (limited to 'contrib/llvm/patches/patch-11-llvm-r231227-aarch64-tls-relocs.diff')
-rw-r--r-- | contrib/llvm/patches/patch-11-llvm-r231227-aarch64-tls-relocs.diff | 811 |
1 files changed, 0 insertions, 811 deletions
diff --git a/contrib/llvm/patches/patch-11-llvm-r231227-aarch64-tls-relocs.diff b/contrib/llvm/patches/patch-11-llvm-r231227-aarch64-tls-relocs.diff deleted file mode 100644 index 5c0edca..0000000 --- a/contrib/llvm/patches/patch-11-llvm-r231227-aarch64-tls-relocs.diff +++ /dev/null @@ -1,811 +0,0 @@ -Pull in r231227 from upstream llvm trunk (by Kristof Beyls): - - Fix PR22408 - LLVM producing AArch64 TLS relocations that GNU linkers - cannot handle yet. - - As is described at http://llvm.org/bugs/show_bug.cgi?id=22408, the - GNU linkers ld.bfd and ld.gold currently only support a subset of the - whole range of AArch64 ELF TLS relocations. Furthermore, they assume - that some of the code sequences to access thread-local variables are - produced in a very specific sequence. When the sequence is not as the - linker expects, it can silently mis-relaxe/mis-optimize the - instructions. - Even if that wouldn't be the case, it's good to produce the exact - sequence, as that ensures that linkers can perform optimizing - relaxations. - - This patch: - - * implements support for 16MiB TLS area size instead of 4GiB TLS area - size. Ideally clang would grow an -mtls-size option to allow - support for both, but that's not part of this patch. - * by default doesn't produce local dynamic access patterns, as even - modern ld.bfd and ld.gold linkers do not support the associated - relocations. An option (-aarch64-elf-ldtls-generation) is added to - enable generation of local dynamic code sequence, but is off by - default. - * makes sure that the exact expected code sequence for local dynamic - and general dynamic accesses is produced, by making use of a new - pseudo instruction. The patch also removes two - (AArch64ISD::TLSDESC_BLR, AArch64ISD::TLSDESC_CALL) pre-existing - AArch64-specific pseudo SDNode instructions that are superseded by - the new one (TLSDESC_CALLSEQ). - -Introduced here: https://svnweb.freebsd.org/changeset/base/280865 - -Index: lib/Target/AArch64/AArch64AsmPrinter.cpp -=================================================================== ---- lib/Target/AArch64/AArch64AsmPrinter.cpp -+++ lib/Target/AArch64/AArch64AsmPrinter.cpp -@@ -12,6 +12,8 @@ - // - //===----------------------------------------------------------------------===// - -+#include "MCTargetDesc/AArch64AddressingModes.h" -+#include "MCTargetDesc/AArch64MCExpr.h" - #include "AArch64.h" - #include "AArch64MCInstLower.h" - #include "AArch64MachineFunctionInfo.h" -@@ -494,12 +496,47 @@ void AArch64AsmPrinter::EmitInstruction(const Mach - EmitToStreamer(OutStreamer, TmpInst); - return; - } -- case AArch64::TLSDESC_BLR: { -- MCOperand Callee, Sym; -- MCInstLowering.lowerOperand(MI->getOperand(0), Callee); -- MCInstLowering.lowerOperand(MI->getOperand(1), Sym); -+ case AArch64::TLSDESC_CALLSEQ: { -+ /// lower this to: -+ /// adrp x0, :tlsdesc:var -+ /// ldr x1, [x0, #:tlsdesc_lo12:var] -+ /// add x0, x0, #:tlsdesc_lo12:var -+ /// .tlsdesccall var -+ /// blr x1 -+ /// (TPIDR_EL0 offset now in x0) -+ const MachineOperand &MO_Sym = MI->getOperand(0); -+ MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym); -+ MCOperand Sym, SymTLSDescLo12, SymTLSDesc; -+ MO_TLSDESC_LO12.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGEOFF | -+ AArch64II::MO_NC); -+ MO_TLSDESC.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGE); -+ MCInstLowering.lowerOperand(MO_Sym, Sym); -+ MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12); -+ MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc); - -- // First emit a relocation-annotation. This expands to no code, but requests -+ MCInst Adrp; -+ Adrp.setOpcode(AArch64::ADRP); -+ Adrp.addOperand(MCOperand::CreateReg(AArch64::X0)); -+ Adrp.addOperand(SymTLSDesc); -+ EmitToStreamer(OutStreamer, Adrp); -+ -+ MCInst Ldr; -+ Ldr.setOpcode(AArch64::LDRXui); -+ Ldr.addOperand(MCOperand::CreateReg(AArch64::X1)); -+ Ldr.addOperand(MCOperand::CreateReg(AArch64::X0)); -+ Ldr.addOperand(SymTLSDescLo12); -+ Ldr.addOperand(MCOperand::CreateImm(0)); -+ EmitToStreamer(OutStreamer, Ldr); -+ -+ MCInst Add; -+ Add.setOpcode(AArch64::ADDXri); -+ Add.addOperand(MCOperand::CreateReg(AArch64::X0)); -+ Add.addOperand(MCOperand::CreateReg(AArch64::X0)); -+ Add.addOperand(SymTLSDescLo12); -+ Add.addOperand(MCOperand::CreateImm(AArch64_AM::getShiftValue(0))); -+ EmitToStreamer(OutStreamer, Add); -+ -+ // Emit a relocation-annotation. This expands to no code, but requests - // the following instruction gets an R_AARCH64_TLSDESC_CALL. - MCInst TLSDescCall; - TLSDescCall.setOpcode(AArch64::TLSDESCCALL); -@@ -506,12 +543,10 @@ void AArch64AsmPrinter::EmitInstruction(const Mach - TLSDescCall.addOperand(Sym); - EmitToStreamer(OutStreamer, TLSDescCall); - -- // Other than that it's just a normal indirect call to the function loaded -- // from the descriptor. -- MCInst BLR; -- BLR.setOpcode(AArch64::BLR); -- BLR.addOperand(Callee); -- EmitToStreamer(OutStreamer, BLR); -+ MCInst Blr; -+ Blr.setOpcode(AArch64::BLR); -+ Blr.addOperand(MCOperand::CreateReg(AArch64::X1)); -+ EmitToStreamer(OutStreamer, Blr); - - return; - } -Index: lib/Target/AArch64/AArch64CleanupLocalDynamicTLSPass.cpp -=================================================================== ---- lib/Target/AArch64/AArch64CleanupLocalDynamicTLSPass.cpp -+++ lib/Target/AArch64/AArch64CleanupLocalDynamicTLSPass.cpp -@@ -62,10 +62,10 @@ struct LDTLSCleanup : public MachineFunctionPass { - for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; - ++I) { - switch (I->getOpcode()) { -- case AArch64::TLSDESC_BLR: -+ case AArch64::TLSDESC_CALLSEQ: - // Make sure it's a local dynamic access. -- if (!I->getOperand(1).isSymbol() || -- strcmp(I->getOperand(1).getSymbolName(), "_TLS_MODULE_BASE_")) -+ if (!I->getOperand(0).isSymbol() || -+ strcmp(I->getOperand(0).getSymbolName(), "_TLS_MODULE_BASE_")) - break; - - if (TLSBaseAddrReg) -Index: lib/Target/AArch64/AArch64ISelLowering.cpp -=================================================================== ---- lib/Target/AArch64/AArch64ISelLowering.cpp -+++ lib/Target/AArch64/AArch64ISelLowering.cpp -@@ -64,10 +64,18 @@ EnableAArch64ExtrGeneration("aarch64-extr-generati - - static cl::opt<bool> - EnableAArch64SlrGeneration("aarch64-shift-insert-generation", cl::Hidden, -- cl::desc("Allow AArch64 SLI/SRI formation"), -- cl::init(false)); -+ cl::desc("Allow AArch64 SLI/SRI formation"), -+ cl::init(false)); - -+// FIXME: The necessary dtprel relocations don't seem to be supported -+// well in the GNU bfd and gold linkers at the moment. Therefore, by -+// default, for now, fall back to GeneralDynamic code generation. -+cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration( -+ "aarch64-elf-ldtls-generation", cl::Hidden, -+ cl::desc("Allow AArch64 Local Dynamic TLS code generation"), -+ cl::init(false)); - -+ - AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM) - : TargetLowering(TM) { - Subtarget = &TM.getSubtarget<AArch64Subtarget>(); -@@ -760,7 +768,7 @@ const char *AArch64TargetLowering::getTargetNodeNa - case AArch64ISD::CSNEG: return "AArch64ISD::CSNEG"; - case AArch64ISD::CSINC: return "AArch64ISD::CSINC"; - case AArch64ISD::THREAD_POINTER: return "AArch64ISD::THREAD_POINTER"; -- case AArch64ISD::TLSDESC_CALL: return "AArch64ISD::TLSDESC_CALL"; -+ case AArch64ISD::TLSDESC_CALLSEQ: return "AArch64ISD::TLSDESC_CALLSEQ"; - case AArch64ISD::ADC: return "AArch64ISD::ADC"; - case AArch64ISD::SBC: return "AArch64ISD::SBC"; - case AArch64ISD::ADDS: return "AArch64ISD::ADDS"; -@@ -3049,61 +3057,34 @@ AArch64TargetLowering::LowerDarwinGlobalTLSAddress - /// When accessing thread-local variables under either the general-dynamic or - /// local-dynamic system, we make a "TLS-descriptor" call. The variable will - /// have a descriptor, accessible via a PC-relative ADRP, and whose first entry --/// is a function pointer to carry out the resolution. This function takes the --/// address of the descriptor in X0 and returns the TPIDR_EL0 offset in X0. All --/// other registers (except LR, NZCV) are preserved. -+/// is a function pointer to carry out the resolution. - /// --/// Thus, the ideal call sequence on AArch64 is: -+/// The sequence is: -+/// adrp x0, :tlsdesc:var -+/// ldr x1, [x0, #:tlsdesc_lo12:var] -+/// add x0, x0, #:tlsdesc_lo12:var -+/// .tlsdesccall var -+/// blr x1 -+/// (TPIDR_EL0 offset now in x0) - /// --/// adrp x0, :tlsdesc:thread_var --/// ldr x8, [x0, :tlsdesc_lo12:thread_var] --/// add x0, x0, :tlsdesc_lo12:thread_var --/// .tlsdesccall thread_var --/// blr x8 --/// (TPIDR_EL0 offset now in x0). --/// --/// The ".tlsdesccall" directive instructs the assembler to insert a particular --/// relocation to help the linker relax this sequence if it turns out to be too --/// conservative. --/// --/// FIXME: we currently produce an extra, duplicated, ADRP instruction, but this --/// is harmless. --SDValue AArch64TargetLowering::LowerELFTLSDescCall(SDValue SymAddr, -- SDValue DescAddr, SDLoc DL, -- SelectionDAG &DAG) const { -+/// The above sequence must be produced unscheduled, to enable the linker to -+/// optimize/relax this sequence. -+/// Therefore, a pseudo-instruction (TLSDESC_CALLSEQ) is used to represent the -+/// above sequence, and expanded really late in the compilation flow, to ensure -+/// the sequence is produced as per above. -+SDValue AArch64TargetLowering::LowerELFTLSDescCallSeq(SDValue SymAddr, SDLoc DL, -+ SelectionDAG &DAG) const { - EVT PtrVT = getPointerTy(); - -- // The function we need to call is simply the first entry in the GOT for this -- // descriptor, load it in preparation. -- SDValue Func = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, SymAddr); -+ SDValue Chain = DAG.getEntryNode(); -+ SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); - -- // TLS calls preserve all registers except those that absolutely must be -- // trashed: X0 (it takes an argument), LR (it's a call) and NZCV (let's not be -- // silly). -- const TargetRegisterInfo *TRI = -- getTargetMachine().getSubtargetImpl()->getRegisterInfo(); -- const AArch64RegisterInfo *ARI = -- static_cast<const AArch64RegisterInfo *>(TRI); -- const uint32_t *Mask = ARI->getTLSCallPreservedMask(); -- -- // The function takes only one argument: the address of the descriptor itself -- // in X0. -- SDValue Glue, Chain; -- Chain = DAG.getCopyToReg(DAG.getEntryNode(), DL, AArch64::X0, DescAddr, Glue); -- Glue = Chain.getValue(1); -- -- // We're now ready to populate the argument list, as with a normal call: -- SmallVector<SDValue, 6> Ops; -+ SmallVector<SDValue, 2> Ops; - Ops.push_back(Chain); -- Ops.push_back(Func); - Ops.push_back(SymAddr); -- Ops.push_back(DAG.getRegister(AArch64::X0, PtrVT)); -- Ops.push_back(DAG.getRegisterMask(Mask)); -- Ops.push_back(Glue); - -- SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); -- Chain = DAG.getNode(AArch64ISD::TLSDESC_CALL, DL, NodeTys, Ops); -- Glue = Chain.getValue(1); -+ Chain = DAG.getNode(AArch64ISD::TLSDESC_CALLSEQ, DL, NodeTys, Ops); -+ SDValue Glue = Chain.getValue(1); - - return DAG.getCopyFromReg(Chain, DL, AArch64::X0, PtrVT, Glue); - } -@@ -3114,9 +3095,18 @@ AArch64TargetLowering::LowerELFGlobalTLSAddress(SD - assert(Subtarget->isTargetELF() && "This function expects an ELF target"); - assert(getTargetMachine().getCodeModel() == CodeModel::Small && - "ELF TLS only supported in small memory model"); -+ // Different choices can be made for the maximum size of the TLS area for a -+ // module. For the small address model, the default TLS size is 16MiB and the -+ // maximum TLS size is 4GiB. -+ // FIXME: add -mtls-size command line option and make it control the 16MiB -+ // vs. 4GiB code sequence generation. - const GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op); - - TLSModel::Model Model = getTargetMachine().getTLSModel(GA->getGlobal()); -+ if (!EnableAArch64ELFLocalDynamicTLSGeneration) { -+ if (Model == TLSModel::LocalDynamic) -+ Model = TLSModel::GeneralDynamic; -+ } - - SDValue TPOff; - EVT PtrVT = getPointerTy(); -@@ -3127,17 +3117,20 @@ AArch64TargetLowering::LowerELFGlobalTLSAddress(SD - - if (Model == TLSModel::LocalExec) { - SDValue HiVar = DAG.getTargetGlobalAddress( -- GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_G1); -+ GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_HI12); - SDValue LoVar = DAG.getTargetGlobalAddress( - GV, DL, PtrVT, 0, -- AArch64II::MO_TLS | AArch64II::MO_G0 | AArch64II::MO_NC); -+ AArch64II::MO_TLS | AArch64II::MO_PAGEOFF | AArch64II::MO_NC); - -- TPOff = SDValue(DAG.getMachineNode(AArch64::MOVZXi, DL, PtrVT, HiVar, -- DAG.getTargetConstant(16, MVT::i32)), -- 0); -- TPOff = SDValue(DAG.getMachineNode(AArch64::MOVKXi, DL, PtrVT, TPOff, LoVar, -- DAG.getTargetConstant(0, MVT::i32)), -- 0); -+ SDValue TPWithOff_lo = -+ SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, ThreadBase, -+ HiVar, DAG.getTargetConstant(0, MVT::i32)), -+ 0); -+ SDValue TPWithOff = -+ SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, TPWithOff_lo, -+ LoVar, DAG.getTargetConstant(0, MVT::i32)), -+ 0); -+ return TPWithOff; - } else if (Model == TLSModel::InitialExec) { - TPOff = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, AArch64II::MO_TLS); - TPOff = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, TPOff); -@@ -3152,19 +3145,6 @@ AArch64TargetLowering::LowerELFGlobalTLSAddress(SD - DAG.getMachineFunction().getInfo<AArch64FunctionInfo>(); - MFI->incNumLocalDynamicTLSAccesses(); - -- // Accesses used in this sequence go via the TLS descriptor which lives in -- // the GOT. Prepare an address we can use to handle this. -- SDValue HiDesc = DAG.getTargetExternalSymbol( -- "_TLS_MODULE_BASE_", PtrVT, AArch64II::MO_TLS | AArch64II::MO_PAGE); -- SDValue LoDesc = DAG.getTargetExternalSymbol( -- "_TLS_MODULE_BASE_", PtrVT, -- AArch64II::MO_TLS | AArch64II::MO_PAGEOFF | AArch64II::MO_NC); -- -- // First argument to the descriptor call is the address of the descriptor -- // itself. -- SDValue DescAddr = DAG.getNode(AArch64ISD::ADRP, DL, PtrVT, HiDesc); -- DescAddr = DAG.getNode(AArch64ISD::ADDlow, DL, PtrVT, DescAddr, LoDesc); -- - // 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 - // the address. -@@ -3173,40 +3153,23 @@ AArch64TargetLowering::LowerELFGlobalTLSAddress(SD - - // Now we can calculate the offset from TPIDR_EL0 to this module's - // thread-local area. -- TPOff = LowerELFTLSDescCall(SymAddr, DescAddr, DL, DAG); -+ TPOff = LowerELFTLSDescCallSeq(SymAddr, DL, DAG); - - // Now use :dtprel_whatever: operations to calculate this variable's offset - // in its thread-storage area. - SDValue HiVar = DAG.getTargetGlobalAddress( -- GV, DL, MVT::i64, 0, AArch64II::MO_TLS | AArch64II::MO_G1); -+ GV, DL, MVT::i64, 0, AArch64II::MO_TLS | AArch64II::MO_HI12); - SDValue LoVar = DAG.getTargetGlobalAddress( - GV, DL, MVT::i64, 0, -- AArch64II::MO_TLS | AArch64II::MO_G0 | AArch64II::MO_NC); -+ AArch64II::MO_TLS | AArch64II::MO_PAGEOFF | AArch64II::MO_NC); - -- SDValue DTPOff = -- SDValue(DAG.getMachineNode(AArch64::MOVZXi, DL, PtrVT, HiVar, -- DAG.getTargetConstant(16, MVT::i32)), -- 0); -- DTPOff = -- SDValue(DAG.getMachineNode(AArch64::MOVKXi, DL, PtrVT, DTPOff, LoVar, -- DAG.getTargetConstant(0, MVT::i32)), -- 0); -- -- TPOff = DAG.getNode(ISD::ADD, DL, PtrVT, TPOff, DTPOff); -+ TPOff = SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, TPOff, HiVar, -+ DAG.getTargetConstant(0, MVT::i32)), -+ 0); -+ TPOff = SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, TPOff, LoVar, -+ DAG.getTargetConstant(0, MVT::i32)), -+ 0); - } else if (Model == TLSModel::GeneralDynamic) { -- // Accesses used in this sequence go via the TLS descriptor which lives in -- // the GOT. Prepare an address we can use to handle this. -- SDValue HiDesc = DAG.getTargetGlobalAddress( -- GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_PAGE); -- SDValue LoDesc = DAG.getTargetGlobalAddress( -- GV, DL, PtrVT, 0, -- AArch64II::MO_TLS | AArch64II::MO_PAGEOFF | AArch64II::MO_NC); -- -- // First argument to the descriptor call is the address of the descriptor -- // itself. -- SDValue DescAddr = DAG.getNode(AArch64ISD::ADRP, DL, PtrVT, HiDesc); -- DescAddr = DAG.getNode(AArch64ISD::ADDlow, DL, PtrVT, DescAddr, LoDesc); -- - // 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 - // the address. -@@ -3214,7 +3177,7 @@ AArch64TargetLowering::LowerELFGlobalTLSAddress(SD - DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, AArch64II::MO_TLS); - - // Finally we can make a call to calculate the offset from tpidr_el0. -- TPOff = LowerELFTLSDescCall(SymAddr, DescAddr, DL, DAG); -+ TPOff = LowerELFTLSDescCallSeq(SymAddr, DL, DAG); - } else - llvm_unreachable("Unsupported ELF TLS access model"); - -Index: lib/Target/AArch64/AArch64ISelLowering.h -=================================================================== ---- lib/Target/AArch64/AArch64ISelLowering.h -+++ lib/Target/AArch64/AArch64ISelLowering.h -@@ -29,9 +29,9 @@ enum { - WrapperLarge, // 4-instruction MOVZ/MOVK sequence for 64-bit addresses. - CALL, // Function call. - -- // Almost the same as a normal call node, except that a TLSDesc relocation is -- // needed so the linker can relax it correctly if possible. -- TLSDESC_CALL, -+ // Produces the full sequence of instructions for getting the thread pointer -+ // offset of a variable into X0, using the TLSDesc model. -+ TLSDESC_CALLSEQ, - ADRP, // Page address of a TargetGlobalAddress operand. - ADDlow, // Add the low 12 bits of a TargetGlobalAddress operand. - LOADgot, // Load from automatically generated descriptor (e.g. Global -@@ -399,8 +399,8 @@ class AArch64TargetLowering : public TargetLowerin - SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerDarwinGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerELFGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; -- SDValue LowerELFTLSDescCall(SDValue SymAddr, SDValue DescAddr, SDLoc DL, -- SelectionDAG &DAG) const; -+ SDValue LowerELFTLSDescCallSeq(SDValue SymAddr, SDLoc DL, -+ SelectionDAG &DAG) const; - SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; -Index: lib/Target/AArch64/AArch64InstrInfo.td -=================================================================== ---- lib/Target/AArch64/AArch64InstrInfo.td -+++ lib/Target/AArch64/AArch64InstrInfo.td -@@ -96,6 +96,19 @@ def SDT_AArch64ITOF : SDTypeProfile<1, 1, [SDTCis - - def SDT_AArch64TLSDescCall : SDTypeProfile<0, -2, [SDTCisPtrTy<0>, - SDTCisPtrTy<1>]>; -+ -+// Generates the general dynamic sequences, i.e. -+// adrp x0, :tlsdesc:var -+// ldr x1, [x0, #:tlsdesc_lo12:var] -+// add x0, x0, #:tlsdesc_lo12:var -+// .tlsdesccall var -+// blr x1 -+ -+// (the TPIDR_EL0 offset is put directly in X0, hence no "result" here) -+// number of operands (the variable) -+def SDT_AArch64TLSDescCallSeq : SDTypeProfile<0,1, -+ [SDTCisPtrTy<0>]>; -+ - def SDT_AArch64WrapperLarge : SDTypeProfile<1, 4, - [SDTCisVT<0, i64>, SDTCisVT<1, i32>, - SDTCisSameAs<1, 2>, SDTCisSameAs<1, 3>, -@@ -229,11 +242,12 @@ def AArch64Prefetch : SDNode<"AArch64ISD::P - def AArch64sitof: SDNode<"AArch64ISD::SITOF", SDT_AArch64ITOF>; - def AArch64uitof: SDNode<"AArch64ISD::UITOF", SDT_AArch64ITOF>; - --def AArch64tlsdesc_call : SDNode<"AArch64ISD::TLSDESC_CALL", -- SDT_AArch64TLSDescCall, -- [SDNPInGlue, SDNPOutGlue, SDNPHasChain, -- SDNPVariadic]>; -+def AArch64tlsdesc_callseq : SDNode<"AArch64ISD::TLSDESC_CALLSEQ", -+ SDT_AArch64TLSDescCallSeq, -+ [SDNPInGlue, SDNPOutGlue, SDNPHasChain, -+ SDNPVariadic]>; - -+ - def AArch64WrapperLarge : SDNode<"AArch64ISD::WrapperLarge", - SDT_AArch64WrapperLarge>; - -@@ -1049,15 +1063,16 @@ def TLSDESCCALL : Pseudo<(outs), (ins i64imm:$sym) - let AsmString = ".tlsdesccall $sym"; - } - --// Pseudo-instruction representing a BLR with attached TLSDESC relocation. It --// gets expanded to two MCInsts during lowering. --let isCall = 1, Defs = [LR] in --def TLSDESC_BLR -- : Pseudo<(outs), (ins GPR64:$dest, i64imm:$sym), -- [(AArch64tlsdesc_call GPR64:$dest, tglobaltlsaddr:$sym)]>; -+// FIXME: maybe the scratch register used shouldn't be fixed to X1? -+// FIXME: can "hasSideEffects be dropped? -+let isCall = 1, Defs = [LR, X0, X1], hasSideEffects = 1, -+ isCodeGenOnly = 1 in -+def TLSDESC_CALLSEQ -+ : Pseudo<(outs), (ins i64imm:$sym), -+ [(AArch64tlsdesc_callseq tglobaltlsaddr:$sym)]>; -+def : Pat<(AArch64tlsdesc_callseq texternalsym:$sym), -+ (TLSDESC_CALLSEQ texternalsym:$sym)>; - --def : Pat<(AArch64tlsdesc_call GPR64:$dest, texternalsym:$sym), -- (TLSDESC_BLR GPR64:$dest, texternalsym:$sym)>; - //===----------------------------------------------------------------------===// - // Conditional branch (immediate) instruction. - //===----------------------------------------------------------------------===// -Index: lib/Target/AArch64/AArch64MCInstLower.cpp -=================================================================== ---- lib/Target/AArch64/AArch64MCInstLower.cpp -+++ lib/Target/AArch64/AArch64MCInstLower.cpp -@@ -22,9 +22,12 @@ - #include "llvm/MC/MCExpr.h" - #include "llvm/MC/MCInst.h" - #include "llvm/Support/CodeGen.h" -+#include "llvm/Support/CommandLine.h" - #include "llvm/Target/TargetMachine.h" - using namespace llvm; - -+extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration; -+ - AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer) - : Ctx(ctx), Printer(printer), TargetTriple(printer.getTargetTriple()) {} - -@@ -84,10 +87,16 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandEL - if (MO.isGlobal()) { - const GlobalValue *GV = MO.getGlobal(); - Model = Printer.TM.getTLSModel(GV); -+ if (!EnableAArch64ELFLocalDynamicTLSGeneration && -+ Model == TLSModel::LocalDynamic) -+ Model = TLSModel::GeneralDynamic; -+ - } else { - assert(MO.isSymbol() && - StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" && - "unexpected external TLS symbol"); -+ // The general dynamic access sequence is used to get the -+ // address of _TLS_MODULE_BASE_. - Model = TLSModel::GeneralDynamic; - } - switch (Model) { -@@ -123,6 +132,8 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandEL - RefFlags |= AArch64MCExpr::VK_G1; - else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0) - RefFlags |= AArch64MCExpr::VK_G0; -+ else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12) -+ RefFlags |= AArch64MCExpr::VK_HI12; - - if (MO.getTargetFlags() & AArch64II::MO_NC) - RefFlags |= AArch64MCExpr::VK_NC; -Index: lib/Target/AArch64/Utils/AArch64BaseInfo.h -=================================================================== ---- lib/Target/AArch64/Utils/AArch64BaseInfo.h -+++ lib/Target/AArch64/Utils/AArch64BaseInfo.h -@@ -1229,7 +1229,7 @@ namespace AArch64II { - - MO_NO_FLAG, - -- MO_FRAGMENT = 0x7, -+ MO_FRAGMENT = 0xf, - - /// MO_PAGE - A symbol operand with this flag represents the pc-relative - /// offset of the 4K page containing the symbol. This is used with the -@@ -1257,26 +1257,31 @@ namespace AArch64II { - /// 0-15 of a 64-bit address, used in a MOVZ or MOVK instruction - MO_G0 = 6, - -+ /// MO_HI12 - This flag indicates that a symbol operand represents the bits -+ /// 13-24 of a 64-bit address, used in a arithmetic immediate-shifted-left- -+ /// by-12-bits instruction. -+ MO_HI12 = 7, -+ - /// MO_GOT - This flag indicates that a symbol operand represents the - /// address of the GOT entry for the symbol, rather than the address of - /// the symbol itself. -- MO_GOT = 8, -+ MO_GOT = 0x10, - - /// MO_NC - Indicates whether the linker is expected to check the symbol - /// reference for overflow. For example in an ADRP/ADD pair of relocations - /// the ADRP usually does check, but not the ADD. -- MO_NC = 0x10, -+ MO_NC = 0x20, - - /// MO_TLS - Indicates that the operand being accessed is some kind of - /// thread-local symbol. On Darwin, only one type of thread-local access - /// exists (pre linker-relaxation), but on ELF the TLSModel used for the - /// referee will affect interpretation. -- MO_TLS = 0x20, -+ MO_TLS = 0x40, - - /// MO_CONSTPOOL - This flag indicates that a symbol operand represents - /// the address of a constant pool entry for the symbol, rather than the - /// address of the symbol itself. -- MO_CONSTPOOL = 0x40 -+ MO_CONSTPOOL = 0x80 - }; - } // end namespace AArch64II - -Index: test/CodeGen/AArch64/arm64-tls-dynamics.ll -=================================================================== ---- test/CodeGen/AArch64/arm64-tls-dynamics.ll -+++ test/CodeGen/AArch64/arm64-tls-dynamics.ll -@@ -1,5 +1,7 @@ --; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -verify-machineinstrs < %s | FileCheck %s --; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-RELOC %s -+; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -verify-machineinstrs < %s | FileCheck %s -+; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-RELOC %s -+; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-NOLD %s -+; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-NOLD-RELOC %s - - @general_dynamic_var = external thread_local global i32 - -@@ -9,22 +11,34 @@ define i32 @test_generaldynamic() { - %val = load i32* @general_dynamic_var - ret i32 %val - -- ; FIXME: the adrp instructions are redundant (if harmless). --; CHECK: adrp [[TLSDESC_HI:x[0-9]+]], :tlsdesc:general_dynamic_var --; CHECK: add x0, [[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var - ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var --; CHECK: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var] --; CHECK: .tlsdesccall general_dynamic_var -+; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var] -+; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var -+; CHECK-NEXT: .tlsdesccall general_dynamic_var - ; CHECK-NEXT: blr [[CALLEE]] - -+; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var -+; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var] -+; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var -+; CHECK-NOLD-NEXT: .tlsdesccall general_dynamic_var -+; CHECK-NOLD-NEXT: blr [[CALLEE]] -+ -+ - ; CHECK: mrs x[[TP:[0-9]+]], TPIDR_EL0 - ; CHECK: ldr w0, [x[[TP]], x0] -+; CHECK-NOLD: mrs x[[TP:[0-9]+]], TPIDR_EL0 -+; CHECK-NOLD: ldr w0, [x[[TP]], x0] - - ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 -+; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC - ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC --; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC - ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL - -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL -+ - } - - define i32* @test_generaldynamic_addr() { -@@ -32,12 +46,10 @@ define i32* @test_generaldynamic_addr() { - - ret i32* @general_dynamic_var - -- ; FIXME: the adrp instructions are redundant (if harmless). --; CHECK: adrp [[TLSDESC_HI:x[0-9]+]], :tlsdesc:general_dynamic_var --; CHECK: add x0, [[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var - ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var --; CHECK: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var] --; CHECK: .tlsdesccall general_dynamic_var -+; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var] -+; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var -+; CHECK-NEXT: .tlsdesccall general_dynamic_var - ; CHECK-NEXT: blr [[CALLEE]] - - ; CHECK: mrs [[TP:x[0-9]+]], TPIDR_EL0 -@@ -44,9 +56,15 @@ define i32* @test_generaldynamic_addr() { - ; CHECK: add x0, [[TP]], x0 - - ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 -+; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC - ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC --; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC - ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL -+ -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL -+ - } - - @local_dynamic_var = external thread_local(localdynamic) global i32 -@@ -58,54 +76,71 @@ define i32 @test_localdynamic() { - ret i32 %val - - ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ --; CHECK: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_ --; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ --; CHECK: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] --; CHECK: .tlsdesccall _TLS_MODULE_BASE_ -+; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] -+; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_ -+; CHECK-NEXT: .tlsdesccall _TLS_MODULE_BASE_ - ; CHECK-NEXT: blr [[CALLEE]] -+; CHECK-NEXT: add x[[TPOFF:[0-9]+]], x0, :dtprel_hi12:local_dynamic_var -+; CHECK-NEXT: add x[[TPOFF]], x[[TPOFF]], :dtprel_lo12_nc:local_dynamic_var -+; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 -+; CHECK: ldr w0, [x[[TPIDR]], x[[TPOFF]]] - --; CHECK: movz [[DTP_OFFSET:x[0-9]+]], #:dtprel_g1:local_dynamic_var --; CHECK: movk [[DTP_OFFSET]], #:dtprel_g0_nc:local_dynamic_var -+; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:local_dynamic_var -+; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var] -+; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var -+; CHECK-NOLD-NEXT: .tlsdesccall local_dynamic_var -+; CHECK-NOLD-NEXT: blr [[CALLEE]] -+; CHECK-NOLD: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 -+; CHECK-NOLD: ldr w0, [x[[TPIDR]], x0] - --; CHECK: add x[[TPREL:[0-9]+]], x0, [[DTP_OFFSET]] - --; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 -- --; CHECK: ldr w0, [x[[TPIDR]], x[[TPREL]]] -- - ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 -+; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC - ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC --; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC - ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL -+; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_HI12 -+; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC - -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL -+ - } - - define i32* @test_localdynamic_addr() { - ; CHECK-LABEL: test_localdynamic_addr: - -- ret i32* @local_dynamic_var -- - ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ --; CHECK: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_ --; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ --; CHECK: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] --; CHECK: .tlsdesccall _TLS_MODULE_BASE_ -+; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] -+; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_ -+; CHECK-NEXT: .tlsdesccall _TLS_MODULE_BASE_ - ; CHECK-NEXT: blr [[CALLEE]] -+; CHECK-NEXT: add x[[TPOFF:[0-9]+]], x0, :dtprel_hi12:local_dynamic_var -+; CHECK-NEXT: add x[[TPOFF]], x[[TPOFF]], :dtprel_lo12_nc:local_dynamic_var -+; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 -+; CHECK: add x0, x[[TPIDR]], x[[TPOFF]] - --; CHECK: movz [[DTP_OFFSET:x[0-9]+]], #:dtprel_g1:local_dynamic_var --; CHECK: movk [[DTP_OFFSET]], #:dtprel_g0_nc:local_dynamic_var -+; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:local_dynamic_var -+; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var] -+; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var -+; CHECK-NOLD-NEXT: .tlsdesccall local_dynamic_var -+; CHECK-NOLD-NEXT: blr [[CALLEE]] -+; CHECK-NOLD: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 -+; CHECK-NOLD: add x0, x[[TPIDR]], x0 -+ ret i32* @local_dynamic_var - --; CHECK: add [[TPREL:x[0-9]+]], x0, [[DTP_OFFSET]] -- --; CHECK: mrs [[TPIDR:x[0-9]+]], TPIDR_EL0 -- --; CHECK: add x0, [[TPIDR]], [[TPREL]] -- - ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 -+; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC - ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC --; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC - ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL -+; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_HI12 -+; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC - -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC -+; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL - } - - ; The entire point of the local-dynamic access model is to have a single call to -@@ -122,11 +157,10 @@ define i32 @test_localdynamic_deduplicate() { - %sum = add i32 %val, %val2 - ret i32 %sum - --; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ --; CHECK: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_ --; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ --; CHECK: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] --; CHECK: .tlsdesccall _TLS_MODULE_BASE_ -+; CHECK: adrp x[[DTPREL_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ -+; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[DTPREL_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] -+; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE -+; CHECK-NEXT: .tlsdesccall _TLS_MODULE_BASE_ - ; CHECK-NEXT: blr [[CALLEE]] - - ; CHECK-NOT: _TLS_MODULE_BASE_ -Index: test/CodeGen/AArch64/arm64-tls-execs.ll -=================================================================== ---- test/CodeGen/AArch64/arm64-tls-execs.ll -+++ test/CodeGen/AArch64/arm64-tls-execs.ll -@@ -38,14 +38,13 @@ define i32 @test_local_exec() { - ; CHECK-LABEL: test_local_exec: - %val = load i32* @local_exec_var - --; CHECK: movz [[TP_OFFSET:x[0-9]+]], #:tprel_g1:local_exec_var // encoding: [0bAAA{{[01]+}},A,0b101AAAAA,0x92] --; CHECK: movk [[TP_OFFSET]], #:tprel_g0_nc:local_exec_var --; CHECK: mrs x[[TP:[0-9]+]], TPIDR_EL0 --; CHECK: ldr w0, [x[[TP]], [[TP_OFFSET]]] -+; 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-RELOC: R_AARCH64_TLSLE_MOVW_TPREL_G1 --; CHECK-RELOC: R_AARCH64_TLSLE_MOVW_TPREL_G0_NC -- -+; CHECK-RELOC: R_AARCH64_TLSLE_ADD_TPREL_HI12 -+; CHECK-RELOC: R_AARCH64_TLSLE_ADD_TPREL_LO12_NC - ret i32 %val - } - -@@ -53,11 +52,11 @@ define i32* @test_local_exec_addr() { - ; CHECK-LABEL: test_local_exec_addr: - ret i32* @local_exec_var - --; CHECK: movz [[TP_OFFSET:x[0-9]+]], #:tprel_g1:local_exec_var --; CHECK: movk [[TP_OFFSET]], #:tprel_g0_nc:local_exec_var --; CHECK: mrs [[TP:x[0-9]+]], TPIDR_EL0 --; CHECK: add x0, [[TP]], [[TP_OFFSET]] -+; CHECK: mrs x[[R1:[0-9]+]], TPIDR_EL0 -+; CHECK: add x[[R2:[0-9]+]], x[[R1]], :tprel_hi12:local_exec_var -+; CHECK: add x0, x[[R2]], :tprel_lo12_nc:local_exec_var -+; CHECK: ret - --; CHECK-RELOC: R_AARCH64_TLSLE_MOVW_TPREL_G1 --; CHECK-RELOC: R_AARCH64_TLSLE_MOVW_TPREL_G0_NC -+; CHECK-RELOC: R_AARCH64_TLSLE_ADD_TPREL_HI12 -+; CHECK-RELOC: R_AARCH64_TLSLE_ADD_TPREL_LO12_NC - } |