xref: /aosp_15_r20/external/llvm/lib/Target/AArch64/AArch64CleanupLocalDynamicTLSPass.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- AArch64CleanupLocalDynamicTLSPass.cpp ---------------------*- C++ -*-=//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // Local-dynamic access to thread-local variables proceeds in three stages.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker // 1. The offset of this Module's thread-local area from TPIDR_EL0 is calculated
13*9880d681SAndroid Build Coastguard Worker //    in much the same way as a general-dynamic TLS-descriptor access against
14*9880d681SAndroid Build Coastguard Worker //    the special symbol _TLS_MODULE_BASE.
15*9880d681SAndroid Build Coastguard Worker // 2. The variable's offset from _TLS_MODULE_BASE_ is calculated using
16*9880d681SAndroid Build Coastguard Worker //    instructions with "dtprel" modifiers.
17*9880d681SAndroid Build Coastguard Worker // 3. These two are added, together with TPIDR_EL0, to obtain the variable's
18*9880d681SAndroid Build Coastguard Worker //    true address.
19*9880d681SAndroid Build Coastguard Worker //
20*9880d681SAndroid Build Coastguard Worker // This is only better than general-dynamic access to the variable if two or
21*9880d681SAndroid Build Coastguard Worker // more of the first stage TLS-descriptor calculations can be combined. This
22*9880d681SAndroid Build Coastguard Worker // pass looks through a function and performs such combinations.
23*9880d681SAndroid Build Coastguard Worker //
24*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
25*9880d681SAndroid Build Coastguard Worker #include "AArch64.h"
26*9880d681SAndroid Build Coastguard Worker #include "AArch64InstrInfo.h"
27*9880d681SAndroid Build Coastguard Worker #include "AArch64MachineFunctionInfo.h"
28*9880d681SAndroid Build Coastguard Worker #include "AArch64TargetMachine.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineDominators.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
34*9880d681SAndroid Build Coastguard Worker using namespace llvm;
35*9880d681SAndroid Build Coastguard Worker 
36*9880d681SAndroid Build Coastguard Worker namespace {
37*9880d681SAndroid Build Coastguard Worker struct LDTLSCleanup : public MachineFunctionPass {
38*9880d681SAndroid Build Coastguard Worker   static char ID;
LDTLSCleanup__anon9e02c4a10111::LDTLSCleanup39*9880d681SAndroid Build Coastguard Worker   LDTLSCleanup() : MachineFunctionPass(ID) {}
40*9880d681SAndroid Build Coastguard Worker 
runOnMachineFunction__anon9e02c4a10111::LDTLSCleanup41*9880d681SAndroid Build Coastguard Worker   bool runOnMachineFunction(MachineFunction &MF) override {
42*9880d681SAndroid Build Coastguard Worker     if (skipFunction(*MF.getFunction()))
43*9880d681SAndroid Build Coastguard Worker       return false;
44*9880d681SAndroid Build Coastguard Worker 
45*9880d681SAndroid Build Coastguard Worker     AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
46*9880d681SAndroid Build Coastguard Worker     if (AFI->getNumLocalDynamicTLSAccesses() < 2) {
47*9880d681SAndroid Build Coastguard Worker       // No point folding accesses if there isn't at least two.
48*9880d681SAndroid Build Coastguard Worker       return false;
49*9880d681SAndroid Build Coastguard Worker     }
50*9880d681SAndroid Build Coastguard Worker 
51*9880d681SAndroid Build Coastguard Worker     MachineDominatorTree *DT = &getAnalysis<MachineDominatorTree>();
52*9880d681SAndroid Build Coastguard Worker     return VisitNode(DT->getRootNode(), 0);
53*9880d681SAndroid Build Coastguard Worker   }
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker   // Visit the dominator subtree rooted at Node in pre-order.
56*9880d681SAndroid Build Coastguard Worker   // If TLSBaseAddrReg is non-null, then use that to replace any
57*9880d681SAndroid Build Coastguard Worker   // TLS_base_addr instructions. Otherwise, create the register
58*9880d681SAndroid Build Coastguard Worker   // when the first such instruction is seen, and then use it
59*9880d681SAndroid Build Coastguard Worker   // as we encounter more instructions.
VisitNode__anon9e02c4a10111::LDTLSCleanup60*9880d681SAndroid Build Coastguard Worker   bool VisitNode(MachineDomTreeNode *Node, unsigned TLSBaseAddrReg) {
61*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *BB = Node->getBlock();
62*9880d681SAndroid Build Coastguard Worker     bool Changed = false;
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker     // Traverse the current block.
65*9880d681SAndroid Build Coastguard Worker     for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); I != E;
66*9880d681SAndroid Build Coastguard Worker          ++I) {
67*9880d681SAndroid Build Coastguard Worker       switch (I->getOpcode()) {
68*9880d681SAndroid Build Coastguard Worker       case AArch64::TLSDESC_CALLSEQ:
69*9880d681SAndroid Build Coastguard Worker         // Make sure it's a local dynamic access.
70*9880d681SAndroid Build Coastguard Worker         if (!I->getOperand(0).isSymbol() ||
71*9880d681SAndroid Build Coastguard Worker             strcmp(I->getOperand(0).getSymbolName(), "_TLS_MODULE_BASE_"))
72*9880d681SAndroid Build Coastguard Worker           break;
73*9880d681SAndroid Build Coastguard Worker 
74*9880d681SAndroid Build Coastguard Worker         if (TLSBaseAddrReg)
75*9880d681SAndroid Build Coastguard Worker           I = replaceTLSBaseAddrCall(*I, TLSBaseAddrReg);
76*9880d681SAndroid Build Coastguard Worker         else
77*9880d681SAndroid Build Coastguard Worker           I = setRegister(*I, &TLSBaseAddrReg);
78*9880d681SAndroid Build Coastguard Worker         Changed = true;
79*9880d681SAndroid Build Coastguard Worker         break;
80*9880d681SAndroid Build Coastguard Worker       default:
81*9880d681SAndroid Build Coastguard Worker         break;
82*9880d681SAndroid Build Coastguard Worker       }
83*9880d681SAndroid Build Coastguard Worker     }
84*9880d681SAndroid Build Coastguard Worker 
85*9880d681SAndroid Build Coastguard Worker     // Visit the children of this block in the dominator tree.
86*9880d681SAndroid Build Coastguard Worker     for (MachineDomTreeNode *N : *Node) {
87*9880d681SAndroid Build Coastguard Worker       Changed |= VisitNode(N, TLSBaseAddrReg);
88*9880d681SAndroid Build Coastguard Worker     }
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker     return Changed;
91*9880d681SAndroid Build Coastguard Worker   }
92*9880d681SAndroid Build Coastguard Worker 
93*9880d681SAndroid Build Coastguard Worker   // Replace the TLS_base_addr instruction I with a copy from
94*9880d681SAndroid Build Coastguard Worker   // TLSBaseAddrReg, returning the new instruction.
replaceTLSBaseAddrCall__anon9e02c4a10111::LDTLSCleanup95*9880d681SAndroid Build Coastguard Worker   MachineInstr *replaceTLSBaseAddrCall(MachineInstr &I,
96*9880d681SAndroid Build Coastguard Worker                                        unsigned TLSBaseAddrReg) {
97*9880d681SAndroid Build Coastguard Worker     MachineFunction *MF = I.getParent()->getParent();
98*9880d681SAndroid Build Coastguard Worker     const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
99*9880d681SAndroid Build Coastguard Worker 
100*9880d681SAndroid Build Coastguard Worker     // Insert a Copy from TLSBaseAddrReg to x0, which is where the rest of the
101*9880d681SAndroid Build Coastguard Worker     // code sequence assumes the address will be.
102*9880d681SAndroid Build Coastguard Worker     MachineInstr *Copy = BuildMI(*I.getParent(), I, I.getDebugLoc(),
103*9880d681SAndroid Build Coastguard Worker                                  TII->get(TargetOpcode::COPY), AArch64::X0)
104*9880d681SAndroid Build Coastguard Worker                              .addReg(TLSBaseAddrReg);
105*9880d681SAndroid Build Coastguard Worker 
106*9880d681SAndroid Build Coastguard Worker     // Erase the TLS_base_addr instruction.
107*9880d681SAndroid Build Coastguard Worker     I.eraseFromParent();
108*9880d681SAndroid Build Coastguard Worker 
109*9880d681SAndroid Build Coastguard Worker     return Copy;
110*9880d681SAndroid Build Coastguard Worker   }
111*9880d681SAndroid Build Coastguard Worker 
112*9880d681SAndroid Build Coastguard Worker   // Create a virtal register in *TLSBaseAddrReg, and populate it by
113*9880d681SAndroid Build Coastguard Worker   // inserting a copy instruction after I. Returns the new instruction.
setRegister__anon9e02c4a10111::LDTLSCleanup114*9880d681SAndroid Build Coastguard Worker   MachineInstr *setRegister(MachineInstr &I, unsigned *TLSBaseAddrReg) {
115*9880d681SAndroid Build Coastguard Worker     MachineFunction *MF = I.getParent()->getParent();
116*9880d681SAndroid Build Coastguard Worker     const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
117*9880d681SAndroid Build Coastguard Worker 
118*9880d681SAndroid Build Coastguard Worker     // Create a virtual register for the TLS base address.
119*9880d681SAndroid Build Coastguard Worker     MachineRegisterInfo &RegInfo = MF->getRegInfo();
120*9880d681SAndroid Build Coastguard Worker     *TLSBaseAddrReg = RegInfo.createVirtualRegister(&AArch64::GPR64RegClass);
121*9880d681SAndroid Build Coastguard Worker 
122*9880d681SAndroid Build Coastguard Worker     // Insert a copy from X0 to TLSBaseAddrReg for later.
123*9880d681SAndroid Build Coastguard Worker     MachineInstr *Copy =
124*9880d681SAndroid Build Coastguard Worker         BuildMI(*I.getParent(), ++I.getIterator(), I.getDebugLoc(),
125*9880d681SAndroid Build Coastguard Worker                 TII->get(TargetOpcode::COPY), *TLSBaseAddrReg)
126*9880d681SAndroid Build Coastguard Worker             .addReg(AArch64::X0);
127*9880d681SAndroid Build Coastguard Worker 
128*9880d681SAndroid Build Coastguard Worker     return Copy;
129*9880d681SAndroid Build Coastguard Worker   }
130*9880d681SAndroid Build Coastguard Worker 
getPassName__anon9e02c4a10111::LDTLSCleanup131*9880d681SAndroid Build Coastguard Worker   const char *getPassName() const override {
132*9880d681SAndroid Build Coastguard Worker     return "Local Dynamic TLS Access Clean-up";
133*9880d681SAndroid Build Coastguard Worker   }
134*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage__anon9e02c4a10111::LDTLSCleanup135*9880d681SAndroid Build Coastguard Worker   void getAnalysisUsage(AnalysisUsage &AU) const override {
136*9880d681SAndroid Build Coastguard Worker     AU.setPreservesCFG();
137*9880d681SAndroid Build Coastguard Worker     AU.addRequired<MachineDominatorTree>();
138*9880d681SAndroid Build Coastguard Worker     MachineFunctionPass::getAnalysisUsage(AU);
139*9880d681SAndroid Build Coastguard Worker   }
140*9880d681SAndroid Build Coastguard Worker };
141*9880d681SAndroid Build Coastguard Worker }
142*9880d681SAndroid Build Coastguard Worker 
143*9880d681SAndroid Build Coastguard Worker char LDTLSCleanup::ID = 0;
createAArch64CleanupLocalDynamicTLSPass()144*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createAArch64CleanupLocalDynamicTLSPass() {
145*9880d681SAndroid Build Coastguard Worker   return new LDTLSCleanup();
146*9880d681SAndroid Build Coastguard Worker }
147