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