123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- //===-- AArch64CleanupLocalDynamicTLSPass.cpp ---------------------*- C++ -*-=//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // Local-dynamic access to thread-local variables proceeds in three stages.
- //
- // 1. The offset of this Module's thread-local area from TPIDR_EL0 is calculated
- // in much the same way as a general-dynamic TLS-descriptor access against
- // the special symbol _TLS_MODULE_BASE.
- // 2. The variable's offset from _TLS_MODULE_BASE_ is calculated using
- // instructions with "dtprel" modifiers.
- // 3. These two are added, together with TPIDR_EL0, to obtain the variable's
- // true address.
- //
- // This is only better than general-dynamic access to the variable if two or
- // more of the first stage TLS-descriptor calculations can be combined. This
- // pass looks through a function and performs such combinations.
- //
- //===----------------------------------------------------------------------===//
- #include "AArch64.h"
- #include "AArch64InstrInfo.h"
- #include "AArch64MachineFunctionInfo.h"
- #include "llvm/CodeGen/MachineDominators.h"
- #include "llvm/CodeGen/MachineFunction.h"
- #include "llvm/CodeGen/MachineFunctionPass.h"
- #include "llvm/CodeGen/MachineInstrBuilder.h"
- #include "llvm/CodeGen/MachineRegisterInfo.h"
- using namespace llvm;
- #define TLSCLEANUP_PASS_NAME "AArch64 Local Dynamic TLS Access Clean-up"
- namespace {
- struct LDTLSCleanup : public MachineFunctionPass {
- static char ID;
- LDTLSCleanup() : MachineFunctionPass(ID) {
- initializeLDTLSCleanupPass(*PassRegistry::getPassRegistry());
- }
- bool runOnMachineFunction(MachineFunction &MF) override {
- if (skipFunction(MF.getFunction()))
- return false;
- AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
- if (AFI->getNumLocalDynamicTLSAccesses() < 2) {
- // No point folding accesses if there isn't at least two.
- return false;
- }
- MachineDominatorTree *DT = &getAnalysis<MachineDominatorTree>();
- return VisitNode(DT->getRootNode(), 0);
- }
- // Visit the dominator subtree rooted at Node in pre-order.
- // If TLSBaseAddrReg is non-null, then use that to replace any
- // TLS_base_addr instructions. Otherwise, create the register
- // when the first such instruction is seen, and then use it
- // as we encounter more instructions.
- bool VisitNode(MachineDomTreeNode *Node, unsigned TLSBaseAddrReg) {
- MachineBasicBlock *BB = Node->getBlock();
- bool Changed = false;
- // Traverse the current block.
- for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); I != E;
- ++I) {
- switch (I->getOpcode()) {
- case AArch64::TLSDESC_CALLSEQ:
- // Make sure it's a local dynamic access.
- if (!I->getOperand(0).isSymbol() ||
- strcmp(I->getOperand(0).getSymbolName(), "_TLS_MODULE_BASE_"))
- break;
- if (TLSBaseAddrReg)
- I = replaceTLSBaseAddrCall(*I, TLSBaseAddrReg);
- else
- I = setRegister(*I, &TLSBaseAddrReg);
- Changed = true;
- break;
- default:
- break;
- }
- }
- // Visit the children of this block in the dominator tree.
- for (MachineDomTreeNode *N : *Node) {
- Changed |= VisitNode(N, TLSBaseAddrReg);
- }
- return Changed;
- }
- // Replace the TLS_base_addr instruction I with a copy from
- // TLSBaseAddrReg, returning the new instruction.
- MachineInstr *replaceTLSBaseAddrCall(MachineInstr &I,
- unsigned TLSBaseAddrReg) {
- MachineFunction *MF = I.getParent()->getParent();
- const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
- // Insert a Copy from TLSBaseAddrReg to x0, which is where the rest of the
- // code sequence assumes the address will be.
- MachineInstr *Copy = BuildMI(*I.getParent(), I, I.getDebugLoc(),
- TII->get(TargetOpcode::COPY), AArch64::X0)
- .addReg(TLSBaseAddrReg);
- // Update the call site info.
- if (I.shouldUpdateCallSiteInfo())
- I.getMF()->eraseCallSiteInfo(&I);
- // Erase the TLS_base_addr instruction.
- I.eraseFromParent();
- return Copy;
- }
- // Create a virtual register in *TLSBaseAddrReg, and populate it by
- // inserting a copy instruction after I. Returns the new instruction.
- MachineInstr *setRegister(MachineInstr &I, unsigned *TLSBaseAddrReg) {
- MachineFunction *MF = I.getParent()->getParent();
- const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
- // Create a virtual register for the TLS base address.
- MachineRegisterInfo &RegInfo = MF->getRegInfo();
- *TLSBaseAddrReg = RegInfo.createVirtualRegister(&AArch64::GPR64RegClass);
- // Insert a copy from X0 to TLSBaseAddrReg for later.
- MachineInstr *Copy =
- BuildMI(*I.getParent(), ++I.getIterator(), I.getDebugLoc(),
- TII->get(TargetOpcode::COPY), *TLSBaseAddrReg)
- .addReg(AArch64::X0);
- return Copy;
- }
- StringRef getPassName() const override { return TLSCLEANUP_PASS_NAME; }
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesCFG();
- AU.addRequired<MachineDominatorTree>();
- MachineFunctionPass::getAnalysisUsage(AU);
- }
- };
- }
- INITIALIZE_PASS(LDTLSCleanup, "aarch64-local-dynamic-tls-cleanup",
- TLSCLEANUP_PASS_NAME, false, false)
- char LDTLSCleanup::ID = 0;
- FunctionPass *llvm::createAArch64CleanupLocalDynamicTLSPass() {
- return new LDTLSCleanup();
- }
|