brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.5 KiB · f17adcc Raw
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