13b0846e8STim Northover //===-- AArch64CleanupLocalDynamicTLSPass.cpp ---------------------*- C++ -*-=//
23b0846e8STim Northover //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63b0846e8STim Northover //
73b0846e8STim Northover //===----------------------------------------------------------------------===//
83b0846e8STim Northover //
93b0846e8STim Northover // Local-dynamic access to thread-local variables proceeds in three stages.
103b0846e8STim Northover //
113b0846e8STim Northover // 1. The offset of this Module's thread-local area from TPIDR_EL0 is calculated
123b0846e8STim Northover // in much the same way as a general-dynamic TLS-descriptor access against
133b0846e8STim Northover // the special symbol _TLS_MODULE_BASE.
143b0846e8STim Northover // 2. The variable's offset from _TLS_MODULE_BASE_ is calculated using
153b0846e8STim Northover // instructions with "dtprel" modifiers.
163b0846e8STim Northover // 3. These two are added, together with TPIDR_EL0, to obtain the variable's
173b0846e8STim Northover // true address.
183b0846e8STim Northover //
193b0846e8STim Northover // This is only better than general-dynamic access to the variable if two or
203b0846e8STim Northover // more of the first stage TLS-descriptor calculations can be combined. This
213b0846e8STim Northover // pass looks through a function and performs such combinations.
223b0846e8STim Northover //
233b0846e8STim Northover //===----------------------------------------------------------------------===//
243b0846e8STim Northover #include "AArch64.h"
253b0846e8STim Northover #include "AArch64InstrInfo.h"
263b0846e8STim Northover #include "AArch64MachineFunctionInfo.h"
273b0846e8STim Northover #include "llvm/CodeGen/MachineDominators.h"
283b0846e8STim Northover #include "llvm/CodeGen/MachineFunction.h"
293b0846e8STim Northover #include "llvm/CodeGen/MachineFunctionPass.h"
303b0846e8STim Northover #include "llvm/CodeGen/MachineInstrBuilder.h"
313b0846e8STim Northover #include "llvm/CodeGen/MachineRegisterInfo.h"
323b0846e8STim Northover using namespace llvm;
333b0846e8STim Northover
34850043b2SDiana Picus #define TLSCLEANUP_PASS_NAME "AArch64 Local Dynamic TLS Access Clean-up"
35850043b2SDiana Picus
363b0846e8STim Northover namespace {
373b0846e8STim Northover struct LDTLSCleanup : public MachineFunctionPass {
383b0846e8STim Northover static char ID;
LDTLSCleanup__anon8245c9390111::LDTLSCleanup39850043b2SDiana Picus LDTLSCleanup() : MachineFunctionPass(ID) {
40850043b2SDiana Picus initializeLDTLSCleanupPass(*PassRegistry::getPassRegistry());
41850043b2SDiana Picus }
423b0846e8STim Northover
runOnMachineFunction__anon8245c9390111::LDTLSCleanup433b0846e8STim Northover bool runOnMachineFunction(MachineFunction &MF) override {
44f1caa283SMatthias Braun if (skipFunction(MF.getFunction()))
451ac98bb0SAndrew Kaylor return false;
461ac98bb0SAndrew Kaylor
473b0846e8STim Northover AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
483b0846e8STim Northover if (AFI->getNumLocalDynamicTLSAccesses() < 2) {
493b0846e8STim Northover // No point folding accesses if there isn't at least two.
503b0846e8STim Northover return false;
513b0846e8STim Northover }
523b0846e8STim Northover
533b0846e8STim Northover MachineDominatorTree *DT = &getAnalysis<MachineDominatorTree>();
543b0846e8STim Northover return VisitNode(DT->getRootNode(), 0);
553b0846e8STim Northover }
563b0846e8STim Northover
573b0846e8STim Northover // Visit the dominator subtree rooted at Node in pre-order.
583b0846e8STim Northover // If TLSBaseAddrReg is non-null, then use that to replace any
593b0846e8STim Northover // TLS_base_addr instructions. Otherwise, create the register
603b0846e8STim Northover // when the first such instruction is seen, and then use it
613b0846e8STim Northover // as we encounter more instructions.
VisitNode__anon8245c9390111::LDTLSCleanup623b0846e8STim Northover bool VisitNode(MachineDomTreeNode *Node, unsigned TLSBaseAddrReg) {
633b0846e8STim Northover MachineBasicBlock *BB = Node->getBlock();
643b0846e8STim Northover bool Changed = false;
653b0846e8STim Northover
663b0846e8STim Northover // Traverse the current block.
673b0846e8STim Northover for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); I != E;
683b0846e8STim Northover ++I) {
693b0846e8STim Northover switch (I->getOpcode()) {
70aea84618SKristof Beyls case AArch64::TLSDESC_CALLSEQ:
713b0846e8STim Northover // Make sure it's a local dynamic access.
72aea84618SKristof Beyls if (!I->getOperand(0).isSymbol() ||
73aea84618SKristof Beyls strcmp(I->getOperand(0).getSymbolName(), "_TLS_MODULE_BASE_"))
743b0846e8STim Northover break;
753b0846e8STim Northover
763b0846e8STim Northover if (TLSBaseAddrReg)
77ab53fd9bSDuncan P. N. Exon Smith I = replaceTLSBaseAddrCall(*I, TLSBaseAddrReg);
783b0846e8STim Northover else
79ab53fd9bSDuncan P. N. Exon Smith I = setRegister(*I, &TLSBaseAddrReg);
803b0846e8STim Northover Changed = true;
813b0846e8STim Northover break;
823b0846e8STim Northover default:
833b0846e8STim Northover break;
843b0846e8STim Northover }
853b0846e8STim Northover }
863b0846e8STim Northover
873b0846e8STim Northover // Visit the children of this block in the dominator tree.
883b0846e8STim Northover for (MachineDomTreeNode *N : *Node) {
893b0846e8STim Northover Changed |= VisitNode(N, TLSBaseAddrReg);
903b0846e8STim Northover }
913b0846e8STim Northover
923b0846e8STim Northover return Changed;
933b0846e8STim Northover }
943b0846e8STim Northover
953b0846e8STim Northover // Replace the TLS_base_addr instruction I with a copy from
963b0846e8STim Northover // TLSBaseAddrReg, returning the new instruction.
replaceTLSBaseAddrCall__anon8245c9390111::LDTLSCleanup97ab53fd9bSDuncan P. N. Exon Smith MachineInstr *replaceTLSBaseAddrCall(MachineInstr &I,
983b0846e8STim Northover unsigned TLSBaseAddrReg) {
99ab53fd9bSDuncan P. N. Exon Smith MachineFunction *MF = I.getParent()->getParent();
100125898a2SEric Christopher const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
1013b0846e8STim Northover
1023b0846e8STim Northover // Insert a Copy from TLSBaseAddrReg to x0, which is where the rest of the
1033b0846e8STim Northover // code sequence assumes the address will be.
104ab53fd9bSDuncan P. N. Exon Smith MachineInstr *Copy = BuildMI(*I.getParent(), I, I.getDebugLoc(),
105ab53fd9bSDuncan P. N. Exon Smith TII->get(TargetOpcode::COPY), AArch64::X0)
106ab53fd9bSDuncan P. N. Exon Smith .addReg(TLSBaseAddrReg);
1073b0846e8STim Northover
1083a4dc577SDjordje Todorovic // Update the call site info.
109*016d91ccSDjordje Todorovic if (I.shouldUpdateCallSiteInfo())
1103a4dc577SDjordje Todorovic I.getMF()->eraseCallSiteInfo(&I);
1113a4dc577SDjordje Todorovic
1123b0846e8STim Northover // Erase the TLS_base_addr instruction.
113ab53fd9bSDuncan P. N. Exon Smith I.eraseFromParent();
1143b0846e8STim Northover
1153b0846e8STim Northover return Copy;
1163b0846e8STim Northover }
1173b0846e8STim Northover
118ddb34d84SHiroshi Inoue // Create a virtual register in *TLSBaseAddrReg, and populate it by
1193b0846e8STim Northover // inserting a copy instruction after I. Returns the new instruction.
setRegister__anon8245c9390111::LDTLSCleanup120ab53fd9bSDuncan P. N. Exon Smith MachineInstr *setRegister(MachineInstr &I, unsigned *TLSBaseAddrReg) {
121ab53fd9bSDuncan P. N. Exon Smith MachineFunction *MF = I.getParent()->getParent();
122125898a2SEric Christopher const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
1233b0846e8STim Northover
1243b0846e8STim Northover // Create a virtual register for the TLS base address.
1253b0846e8STim Northover MachineRegisterInfo &RegInfo = MF->getRegInfo();
1263b0846e8STim Northover *TLSBaseAddrReg = RegInfo.createVirtualRegister(&AArch64::GPR64RegClass);
1273b0846e8STim Northover
1283b0846e8STim Northover // Insert a copy from X0 to TLSBaseAddrReg for later.
129d389165cSDuncan P. N. Exon Smith MachineInstr *Copy =
130ab53fd9bSDuncan P. N. Exon Smith BuildMI(*I.getParent(), ++I.getIterator(), I.getDebugLoc(),
131769e1a97SDuncan P. N. Exon Smith TII->get(TargetOpcode::COPY), *TLSBaseAddrReg)
132d389165cSDuncan P. N. Exon Smith .addReg(AArch64::X0);
1333b0846e8STim Northover
1343b0846e8STim Northover return Copy;
1353b0846e8STim Northover }
1363b0846e8STim Northover
getPassName__anon8245c9390111::LDTLSCleanup137117296c0SMehdi Amini StringRef getPassName() const override { return TLSCLEANUP_PASS_NAME; }
1383b0846e8STim Northover
getAnalysisUsage__anon8245c9390111::LDTLSCleanup1393b0846e8STim Northover void getAnalysisUsage(AnalysisUsage &AU) const override {
1403b0846e8STim Northover AU.setPreservesCFG();
1413b0846e8STim Northover AU.addRequired<MachineDominatorTree>();
1423b0846e8STim Northover MachineFunctionPass::getAnalysisUsage(AU);
1433b0846e8STim Northover }
1443b0846e8STim Northover };
145f00654e3SAlexander Kornienko }
1463b0846e8STim Northover
147850043b2SDiana Picus INITIALIZE_PASS(LDTLSCleanup, "aarch64-local-dynamic-tls-cleanup",
148850043b2SDiana Picus TLSCLEANUP_PASS_NAME, false, false)
149850043b2SDiana Picus
1503b0846e8STim Northover char LDTLSCleanup::ID = 0;
createAArch64CleanupLocalDynamicTLSPass()1513b0846e8STim Northover FunctionPass *llvm::createAArch64CleanupLocalDynamicTLSPass() {
1523b0846e8STim Northover return new LDTLSCleanup();
1533b0846e8STim Northover }
154