| //===- X86CleanupLocalDynamicTLS.cpp - Cleanup local dynamic TLS access ---===// | |
| // | |
| // 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 | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This pass combines multiple accesses to local-dynamic TLS variables so that | |
| // the TLS base address for the module is only fetched once per execution path | |
| // through the function. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "X86.h" | |
| #include "X86InstrInfo.h" | |
| #include "X86MachineFunctionInfo.h" | |
| #include "X86Subtarget.h" | |
| #include "llvm/CodeGen/MachineDominators.h" | |
| #include "llvm/CodeGen/MachineFunctionPass.h" | |
| #include "llvm/CodeGen/MachineInstrBuilder.h" | |
| #include "llvm/CodeGen/MachineRegisterInfo.h" | |
| using namespace llvm; | |
| #define DEBUG_TYPE "x86-cleanup-local-dynamic-tls" | |
| namespace { | |
| class X86CleanupLocalDynamicTLSLegacy : public MachineFunctionPass { | |
| public: | |
| static char ID; | |
| X86CleanupLocalDynamicTLSLegacy() : MachineFunctionPass(ID) {} | |
| StringRef getPassName() const override { | |
| return "Local Dynamic TLS Access Clean-up"; | |
| } | |
| bool runOnMachineFunction(MachineFunction &MF) override; | |
| void getAnalysisUsage(AnalysisUsage &AU) const override { | |
| AU.setPreservesCFG(); | |
| AU.addRequired<MachineDominatorTreeWrapperPass>(); | |
| MachineFunctionPass::getAnalysisUsage(AU); | |
| } | |
| }; | |
| } // end anonymous namespace | |
| char X86CleanupLocalDynamicTLSLegacy::ID = 0; | |
| FunctionPass *llvm::createCleanupLocalDynamicTLSLegacyPass() { | |
| return new X86CleanupLocalDynamicTLSLegacy(); | |
| } | |
| // Replace the TLS_base_addr instruction I with a copy from | |
| // TLSBaseAddrReg, returning the new instruction. | |
| static MachineInstr *ReplaceTLSBaseAddrCall(MachineInstr &I, | |
| Register TLSBaseAddrReg) { | |
| MachineFunction *MF = I.getParent()->getParent(); | |
| const X86Subtarget &STI = MF->getSubtarget<X86Subtarget>(); | |
| const bool is64Bit = STI.is64Bit(); | |
| const X86InstrInfo *TII = STI.getInstrInfo(); | |
| // Insert a Copy from TLSBaseAddrReg to RAX/EAX. | |
| MachineInstr *Copy = | |
| BuildMI(*I.getParent(), I, I.getDebugLoc(), TII->get(TargetOpcode::COPY), | |
| is64Bit ? X86::RAX : X86::EAX) | |
| .addReg(TLSBaseAddrReg); | |
| // 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. | |
| static MachineInstr *SetRegister(MachineInstr &I, Register *TLSBaseAddrReg) { | |
| MachineFunction *MF = I.getParent()->getParent(); | |
| const X86Subtarget &STI = MF->getSubtarget<X86Subtarget>(); | |
| const bool is64Bit = STI.is64Bit(); | |
| const X86InstrInfo *TII = STI.getInstrInfo(); | |
| // Create a virtual register for the TLS base address. | |
| MachineRegisterInfo &RegInfo = MF->getRegInfo(); | |
| *TLSBaseAddrReg = RegInfo.createVirtualRegister(is64Bit ? &X86::GR64RegClass | |
| : &X86::GR32RegClass); | |
| // Insert a copy from RAX/EAX to TLSBaseAddrReg. | |
| MachineInstr *Next = I.getNextNode(); | |
| MachineInstr *Copy = BuildMI(*I.getParent(), Next, I.getDebugLoc(), | |
| TII->get(TargetOpcode::COPY), *TLSBaseAddrReg) | |
| .addReg(is64Bit ? X86::RAX : X86::EAX); | |
| return Copy; | |
| } | |
| // 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. | |
| static bool VisitNode(MachineDomTreeNode *Node, Register 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 X86::TLS_base_addr32: | |
| case X86::TLS_base_addr64: | |
| 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 *I : Node->children()) | |
| Changed |= VisitNode(I, TLSBaseAddrReg); | |
| return Changed; | |
| } | |
| static bool cleanupLocalDynamicTLS(MachineDominatorTree &DT) { | |
| return VisitNode(DT.getRootNode(), Register()); | |
| } | |
| static bool shouldSkipLocalDynamicTLS(MachineFunction &MF) { | |
| X86MachineFunctionInfo *MFI = MF.getInfo<X86MachineFunctionInfo>(); | |
| if (MFI->getNumLocalDynamicTLSAccesses() < 2) { | |
| // No point folding accesses if there isn't at least two. | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool X86CleanupLocalDynamicTLSLegacy::runOnMachineFunction( | |
| MachineFunction &MF) { | |
| if (skipFunction(MF.getFunction()) || shouldSkipLocalDynamicTLS(MF)) | |
| return false; | |
| MachineDominatorTree &DT = | |
| getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree(); | |
| return cleanupLocalDynamicTLS(DT); | |
| } | |
| PreservedAnalyses | |
| X86CleanupLocalDynamicTLSPass::run(MachineFunction &MF, | |
| MachineFunctionAnalysisManager &MFAM) { | |
| if (shouldSkipLocalDynamicTLS(MF)) | |
| return PreservedAnalyses::all(); | |
| MachineDominatorTree &DT = MFAM.getResult<MachineDominatorTreeAnalysis>(MF); | |
| return cleanupLocalDynamicTLS(DT) ? getMachineFunctionPassPreservedAnalyses() | |
| .preserveSet<CFGAnalyses>() | |
| : PreservedAnalyses::all(); | |
| } |