10b57cec5SDimitry Andric //===-- SystemZLDCleanup.cpp - Clean up local-dynamic TLS accesses --------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This pass combines multiple accesses to local-dynamic TLS variables so that
100b57cec5SDimitry Andric // the TLS base address for the module is only fetched once per execution path
110b57cec5SDimitry Andric // through the function.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "SystemZMachineFunctionInfo.h"
160b57cec5SDimitry Andric #include "SystemZTargetMachine.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
230b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric namespace {
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric class SystemZLDCleanup : public MachineFunctionPass {
300b57cec5SDimitry Andric public:
310b57cec5SDimitry Andric static char ID;
SystemZLDCleanup()3204eeddc0SDimitry Andric SystemZLDCleanup() : MachineFunctionPass(ID), TII(nullptr), MF(nullptr) {
3304eeddc0SDimitry Andric initializeSystemZLDCleanupPass(*PassRegistry::getPassRegistry());
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
370b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override;
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric private:
400b57cec5SDimitry Andric bool VisitNode(MachineDomTreeNode *Node, unsigned TLSBaseAddrReg);
410b57cec5SDimitry Andric MachineInstr *ReplaceTLSCall(MachineInstr *I, unsigned TLSBaseAddrReg);
420b57cec5SDimitry Andric MachineInstr *SetRegister(MachineInstr *I, unsigned *TLSBaseAddrReg);
430b57cec5SDimitry Andric
440b57cec5SDimitry Andric const SystemZInstrInfo *TII;
450b57cec5SDimitry Andric MachineFunction *MF;
460b57cec5SDimitry Andric };
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric char SystemZLDCleanup::ID = 0;
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric } // end anonymous namespace
510b57cec5SDimitry Andric
5204eeddc0SDimitry Andric INITIALIZE_PASS(SystemZLDCleanup, "systemz-ld-cleanup",
5304eeddc0SDimitry Andric "SystemZ Local Dynamic TLS Access Clean-up", false, false)
5404eeddc0SDimitry Andric
createSystemZLDCleanupPass(SystemZTargetMachine & TM)550b57cec5SDimitry Andric FunctionPass *llvm::createSystemZLDCleanupPass(SystemZTargetMachine &TM) {
5604eeddc0SDimitry Andric return new SystemZLDCleanup();
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const590b57cec5SDimitry Andric void SystemZLDCleanup::getAnalysisUsage(AnalysisUsage &AU) const {
600b57cec5SDimitry Andric AU.setPreservesCFG();
61*0fca6ea1SDimitry Andric AU.addRequired<MachineDominatorTreeWrapperPass>();
620b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric
runOnMachineFunction(MachineFunction & F)650b57cec5SDimitry Andric bool SystemZLDCleanup::runOnMachineFunction(MachineFunction &F) {
660b57cec5SDimitry Andric if (skipFunction(F.getFunction()))
670b57cec5SDimitry Andric return false;
680b57cec5SDimitry Andric
6981ad6265SDimitry Andric TII = F.getSubtarget<SystemZSubtarget>().getInstrInfo();
700b57cec5SDimitry Andric MF = &F;
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric SystemZMachineFunctionInfo* MFI = F.getInfo<SystemZMachineFunctionInfo>();
730b57cec5SDimitry Andric if (MFI->getNumLocalDynamicTLSAccesses() < 2) {
740b57cec5SDimitry Andric // No point folding accesses if there isn't at least two.
750b57cec5SDimitry Andric return false;
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric
78*0fca6ea1SDimitry Andric MachineDominatorTree *DT =
79*0fca6ea1SDimitry Andric &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
800b57cec5SDimitry Andric return VisitNode(DT->getRootNode(), 0);
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric // Visit the dominator subtree rooted at Node in pre-order.
840b57cec5SDimitry Andric // If TLSBaseAddrReg is non-null, then use that to replace any
850b57cec5SDimitry Andric // TLS_LDCALL instructions. Otherwise, create the register
860b57cec5SDimitry Andric // when the first such instruction is seen, and then use it
870b57cec5SDimitry Andric // as we encounter more instructions.
VisitNode(MachineDomTreeNode * Node,unsigned TLSBaseAddrReg)880b57cec5SDimitry Andric bool SystemZLDCleanup::VisitNode(MachineDomTreeNode *Node,
890b57cec5SDimitry Andric unsigned TLSBaseAddrReg) {
900b57cec5SDimitry Andric MachineBasicBlock *BB = Node->getBlock();
910b57cec5SDimitry Andric bool Changed = false;
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric // Traverse the current block.
940b57cec5SDimitry Andric for (auto I = BB->begin(), E = BB->end(); I != E; ++I) {
950b57cec5SDimitry Andric switch (I->getOpcode()) {
960b57cec5SDimitry Andric case SystemZ::TLS_LDCALL:
970b57cec5SDimitry Andric if (TLSBaseAddrReg)
980b57cec5SDimitry Andric I = ReplaceTLSCall(&*I, TLSBaseAddrReg);
990b57cec5SDimitry Andric else
1000b57cec5SDimitry Andric I = SetRegister(&*I, &TLSBaseAddrReg);
1010b57cec5SDimitry Andric Changed = true;
1020b57cec5SDimitry Andric break;
1030b57cec5SDimitry Andric default:
1040b57cec5SDimitry Andric break;
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric // Visit the children of this block in the dominator tree.
109bdd1243dSDimitry Andric for (auto &N : *Node)
110bdd1243dSDimitry Andric Changed |= VisitNode(N, TLSBaseAddrReg);
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andric return Changed;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
1150b57cec5SDimitry Andric // Replace the TLS_LDCALL instruction I with a copy from TLSBaseAddrReg,
1160b57cec5SDimitry Andric // returning the new instruction.
ReplaceTLSCall(MachineInstr * I,unsigned TLSBaseAddrReg)1170b57cec5SDimitry Andric MachineInstr *SystemZLDCleanup::ReplaceTLSCall(MachineInstr *I,
1180b57cec5SDimitry Andric unsigned TLSBaseAddrReg) {
1190b57cec5SDimitry Andric // Insert a Copy from TLSBaseAddrReg to R2.
1200b57cec5SDimitry Andric MachineInstr *Copy = BuildMI(*I->getParent(), I, I->getDebugLoc(),
1210b57cec5SDimitry Andric TII->get(TargetOpcode::COPY), SystemZ::R2D)
1220b57cec5SDimitry Andric .addReg(TLSBaseAddrReg);
1230b57cec5SDimitry Andric
1240b57cec5SDimitry Andric // Erase the TLS_LDCALL instruction.
1250b57cec5SDimitry Andric I->eraseFromParent();
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric return Copy;
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric // Create a virtual register in *TLSBaseAddrReg, and populate it by
1310b57cec5SDimitry Andric // inserting a copy instruction after I. Returns the new instruction.
SetRegister(MachineInstr * I,unsigned * TLSBaseAddrReg)1320b57cec5SDimitry Andric MachineInstr *SystemZLDCleanup::SetRegister(MachineInstr *I,
1330b57cec5SDimitry Andric unsigned *TLSBaseAddrReg) {
1340b57cec5SDimitry Andric // Create a virtual register for the TLS base address.
1350b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = MF->getRegInfo();
1360b57cec5SDimitry Andric *TLSBaseAddrReg = RegInfo.createVirtualRegister(&SystemZ::GR64BitRegClass);
1370b57cec5SDimitry Andric
1380b57cec5SDimitry Andric // Insert a copy from R2 to TLSBaseAddrReg.
1390b57cec5SDimitry Andric MachineInstr *Next = I->getNextNode();
1400b57cec5SDimitry Andric MachineInstr *Copy = BuildMI(*I->getParent(), Next, I->getDebugLoc(),
1410b57cec5SDimitry Andric TII->get(TargetOpcode::COPY), *TLSBaseAddrReg)
1420b57cec5SDimitry Andric .addReg(SystemZ::R2D);
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric return Copy;
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric
147