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