Home | History | Annotate | Download | only in SystemZ
      1 //===-- SystemZLDCleanup.cpp - Clean up local-dynamic TLS accesses --------===//
      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 // This pass combines multiple accesses to local-dynamic TLS variables so that
     11 // the TLS base address for the module is only fetched once per execution path
     12 // through the function.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #include "SystemZTargetMachine.h"
     17 #include "SystemZMachineFunctionInfo.h"
     18 #include "llvm/CodeGen/MachineDominators.h"
     19 #include "llvm/CodeGen/MachineFunctionPass.h"
     20 #include "llvm/CodeGen/MachineInstrBuilder.h"
     21 #include "llvm/CodeGen/MachineRegisterInfo.h"
     22 #include "llvm/Target/TargetInstrInfo.h"
     23 #include "llvm/Target/TargetMachine.h"
     24 #include "llvm/Target/TargetRegisterInfo.h"
     25 
     26 using namespace llvm;
     27 
     28 namespace {
     29 
     30 class SystemZLDCleanup : public MachineFunctionPass {
     31 public:
     32   static char ID;
     33   SystemZLDCleanup(const SystemZTargetMachine &tm)
     34     : MachineFunctionPass(ID), TII(nullptr), MF(nullptr) {}
     35 
     36   const char *getPassName() const override {
     37     return "SystemZ Local Dynamic TLS Access Clean-up";
     38   }
     39 
     40   bool runOnMachineFunction(MachineFunction &MF) override;
     41   void getAnalysisUsage(AnalysisUsage &AU) const override;
     42 
     43 private:
     44   bool VisitNode(MachineDomTreeNode *Node, unsigned TLSBaseAddrReg);
     45   MachineInstr *ReplaceTLSCall(MachineInstr *I, unsigned TLSBaseAddrReg);
     46   MachineInstr *SetRegister(MachineInstr *I, unsigned *TLSBaseAddrReg);
     47 
     48   const SystemZInstrInfo *TII;
     49   MachineFunction *MF;
     50 };
     51 
     52 char SystemZLDCleanup::ID = 0;
     53 
     54 } // end anonymous namespace
     55 
     56 FunctionPass *llvm::createSystemZLDCleanupPass(SystemZTargetMachine &TM) {
     57   return new SystemZLDCleanup(TM);
     58 }
     59 
     60 void SystemZLDCleanup::getAnalysisUsage(AnalysisUsage &AU) const {
     61   AU.setPreservesCFG();
     62   AU.addRequired<MachineDominatorTree>();
     63   MachineFunctionPass::getAnalysisUsage(AU);
     64 }
     65 
     66 bool SystemZLDCleanup::runOnMachineFunction(MachineFunction &F) {
     67   if (skipFunction(*F.getFunction()))
     68     return false;
     69 
     70   TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo());
     71   MF = &F;
     72 
     73   SystemZMachineFunctionInfo* MFI = F.getInfo<SystemZMachineFunctionInfo>();
     74   if (MFI->getNumLocalDynamicTLSAccesses() < 2) {
     75     // No point folding accesses if there isn't at least two.
     76     return false;
     77   }
     78 
     79   MachineDominatorTree *DT = &getAnalysis<MachineDominatorTree>();
     80   return VisitNode(DT->getRootNode(), 0);
     81 }
     82 
     83 // Visit the dominator subtree rooted at Node in pre-order.
     84 // If TLSBaseAddrReg is non-null, then use that to replace any
     85 // TLS_LDCALL instructions. Otherwise, create the register
     86 // when the first such instruction is seen, and then use it
     87 // as we encounter more instructions.
     88 bool SystemZLDCleanup::VisitNode(MachineDomTreeNode *Node,
     89                                  unsigned TLSBaseAddrReg) {
     90   MachineBasicBlock *BB = Node->getBlock();
     91   bool Changed = false;
     92 
     93   // Traverse the current block.
     94   for (auto I = BB->begin(), E = BB->end(); I != E; ++I) {
     95     switch (I->getOpcode()) {
     96       case SystemZ::TLS_LDCALL:
     97         if (TLSBaseAddrReg)
     98           I = ReplaceTLSCall(&*I, TLSBaseAddrReg);
     99         else
    100           I = SetRegister(&*I, &TLSBaseAddrReg);
    101         Changed = true;
    102         break;
    103       default:
    104         break;
    105     }
    106   }
    107 
    108   // Visit the children of this block in the dominator tree.
    109   for (auto I = Node->begin(), E = Node->end(); I != E; ++I)
    110     Changed |= VisitNode(*I, TLSBaseAddrReg);
    111 
    112   return Changed;
    113 }
    114 
    115 // Replace the TLS_LDCALL instruction I with a copy from TLSBaseAddrReg,
    116 // returning the new instruction.
    117 MachineInstr *SystemZLDCleanup::ReplaceTLSCall(MachineInstr *I,
    118                                                unsigned TLSBaseAddrReg) {
    119   // Insert a Copy from TLSBaseAddrReg to R2.
    120   MachineInstr *Copy = BuildMI(*I->getParent(), I, I->getDebugLoc(),
    121                                TII->get(TargetOpcode::COPY), SystemZ::R2D)
    122                                .addReg(TLSBaseAddrReg);
    123 
    124   // Erase the TLS_LDCALL instruction.
    125   I->eraseFromParent();
    126 
    127   return Copy;
    128 }
    129 
    130 // Create a virtal register in *TLSBaseAddrReg, and populate it by
    131 // inserting a copy instruction after I. Returns the new instruction.
    132 MachineInstr *SystemZLDCleanup::SetRegister(MachineInstr *I,
    133                                             unsigned *TLSBaseAddrReg) {
    134   // Create a virtual register for the TLS base address.
    135   MachineRegisterInfo &RegInfo = MF->getRegInfo();
    136   *TLSBaseAddrReg = RegInfo.createVirtualRegister(&SystemZ::GR64BitRegClass);
    137 
    138   // Insert a copy from R2 to TLSBaseAddrReg.
    139   MachineInstr *Next = I->getNextNode();
    140   MachineInstr *Copy = BuildMI(*I->getParent(), Next, I->getDebugLoc(),
    141                                TII->get(TargetOpcode::COPY), *TLSBaseAddrReg)
    142                                .addReg(SystemZ::R2D);
    143 
    144   return Copy;
    145 }
    146 
    147