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