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