]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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 "AArch64TargetMachine.h" | |
29 | #include "llvm/CodeGen/MachineDominators.h" | |
30 | #include "llvm/CodeGen/MachineFunction.h" | |
31 | #include "llvm/CodeGen/MachineFunctionPass.h" | |
32 | #include "llvm/CodeGen/MachineInstrBuilder.h" | |
33 | #include "llvm/CodeGen/MachineRegisterInfo.h" | |
34 | using namespace llvm; | |
35 | ||
36 | namespace { | |
37 | struct LDTLSCleanup : public MachineFunctionPass { | |
38 | static char ID; | |
39 | LDTLSCleanup() : MachineFunctionPass(ID) {} | |
40 | ||
41 | bool runOnMachineFunction(MachineFunction &MF) override { | |
42 | AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>(); | |
43 | if (AFI->getNumLocalDynamicTLSAccesses() < 2) { | |
44 | // No point folding accesses if there isn't at least two. | |
45 | return false; | |
46 | } | |
47 | ||
48 | MachineDominatorTree *DT = &getAnalysis<MachineDominatorTree>(); | |
49 | return VisitNode(DT->getRootNode(), 0); | |
50 | } | |
51 | ||
52 | // Visit the dominator subtree rooted at Node in pre-order. | |
53 | // If TLSBaseAddrReg is non-null, then use that to replace any | |
54 | // TLS_base_addr instructions. Otherwise, create the register | |
55 | // when the first such instruction is seen, and then use it | |
56 | // as we encounter more instructions. | |
57 | bool VisitNode(MachineDomTreeNode *Node, unsigned TLSBaseAddrReg) { | |
58 | MachineBasicBlock *BB = Node->getBlock(); | |
59 | bool Changed = false; | |
60 | ||
61 | // Traverse the current block. | |
62 | for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; | |
63 | ++I) { | |
64 | switch (I->getOpcode()) { | |
65 | case AArch64::TLSDESC_BLR: | |
66 | // Make sure it's a local dynamic access. | |
67 | if (!I->getOperand(1).isSymbol() || | |
68 | strcmp(I->getOperand(1).getSymbolName(), "_TLS_MODULE_BASE_")) | |
69 | break; | |
70 | ||
71 | if (TLSBaseAddrReg) | |
72 | I = replaceTLSBaseAddrCall(I, TLSBaseAddrReg); | |
73 | else | |
74 | I = setRegister(I, &TLSBaseAddrReg); | |
75 | Changed = true; | |
76 | break; | |
77 | default: | |
78 | break; | |
79 | } | |
80 | } | |
81 | ||
82 | // Visit the children of this block in the dominator tree. | |
83 | for (MachineDomTreeNode *N : *Node) { | |
84 | Changed |= VisitNode(N, TLSBaseAddrReg); | |
85 | } | |
86 | ||
87 | return Changed; | |
88 | } | |
89 | ||
90 | // Replace the TLS_base_addr instruction I with a copy from | |
91 | // TLSBaseAddrReg, returning the new instruction. | |
92 | MachineInstr *replaceTLSBaseAddrCall(MachineInstr *I, | |
93 | unsigned TLSBaseAddrReg) { | |
94 | MachineFunction *MF = I->getParent()->getParent(); | |
95 | const AArch64TargetMachine *TM = | |
96 | static_cast<const AArch64TargetMachine *>(&MF->getTarget()); | |
97 | const AArch64InstrInfo *TII = TM->getSubtargetImpl()->getInstrInfo(); | |
98 | ||
99 | // Insert a Copy from TLSBaseAddrReg to x0, which is where the rest of the | |
100 | // code sequence assumes the address will be. | |
101 | MachineInstr *Copy = BuildMI(*I->getParent(), I, I->getDebugLoc(), | |
102 | TII->get(TargetOpcode::COPY), | |
103 | AArch64::X0).addReg(TLSBaseAddrReg); | |
104 | ||
105 | // Erase the TLS_base_addr instruction. | |
106 | I->eraseFromParent(); | |
107 | ||
108 | return Copy; | |
109 | } | |
110 | ||
111 | // Create a virtal register in *TLSBaseAddrReg, and populate it by | |
112 | // inserting a copy instruction after I. Returns the new instruction. | |
113 | MachineInstr *setRegister(MachineInstr *I, unsigned *TLSBaseAddrReg) { | |
114 | MachineFunction *MF = I->getParent()->getParent(); | |
115 | const AArch64TargetMachine *TM = | |
116 | static_cast<const AArch64TargetMachine *>(&MF->getTarget()); | |
117 | const AArch64InstrInfo *TII = TM->getSubtargetImpl()->getInstrInfo(); | |
118 | ||
119 | // Create a virtual register for the TLS base address. | |
120 | MachineRegisterInfo &RegInfo = MF->getRegInfo(); | |
121 | *TLSBaseAddrReg = RegInfo.createVirtualRegister(&AArch64::GPR64RegClass); | |
122 | ||
123 | // Insert a copy from X0 to TLSBaseAddrReg for later. | |
124 | MachineInstr *Next = I->getNextNode(); | |
125 | MachineInstr *Copy = BuildMI(*I->getParent(), Next, I->getDebugLoc(), | |
126 | TII->get(TargetOpcode::COPY), | |
127 | *TLSBaseAddrReg).addReg(AArch64::X0); | |
128 | ||
129 | return Copy; | |
130 | } | |
131 | ||
132 | const char *getPassName() const override { | |
133 | return "Local Dynamic TLS Access Clean-up"; | |
134 | } | |
135 | ||
136 | void getAnalysisUsage(AnalysisUsage &AU) const override { | |
137 | AU.setPreservesCFG(); | |
138 | AU.addRequired<MachineDominatorTree>(); | |
139 | MachineFunctionPass::getAnalysisUsage(AU); | |
140 | } | |
141 | }; | |
142 | } | |
143 | ||
144 | char LDTLSCleanup::ID = 0; | |
145 | FunctionPass *llvm::createAArch64CleanupLocalDynamicTLSPass() { | |
146 | return new LDTLSCleanup(); | |
147 | } |