1*0b57cec5SDimitry Andric //===---------- PPCTLSDynamicCall.cpp - TLS Dynamic Call Fixup ------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This pass expands ADDItls{ld,gd}LADDR[32] machine instructions into 10*0b57cec5SDimitry Andric // separate ADDItls[gd]L[32] and GETtlsADDR[32] instructions, both of 11*0b57cec5SDimitry Andric // which define GPR3. A copy is added from GPR3 to the target virtual 12*0b57cec5SDimitry Andric // register of the original instruction. The GETtlsADDR[32] is really 13*0b57cec5SDimitry Andric // a call instruction, so its target register is constrained to be GPR3. 14*0b57cec5SDimitry Andric // This is not true of ADDItls[gd]L[32], but there is a legacy linker 15*0b57cec5SDimitry Andric // optimization bug that requires the target register of the addi of 16*0b57cec5SDimitry Andric // a local- or general-dynamic TLS access sequence to be GPR3. 17*0b57cec5SDimitry Andric // 18*0b57cec5SDimitry Andric // This is done in a late pass so that TLS variable accesses can be 19*0b57cec5SDimitry Andric // fully commoned by MachineCSE. 20*0b57cec5SDimitry Andric // 21*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andric #include "PPC.h" 24*0b57cec5SDimitry Andric #include "PPCInstrBuilder.h" 25*0b57cec5SDimitry Andric #include "PPCInstrInfo.h" 26*0b57cec5SDimitry Andric #include "PPCTargetMachine.h" 27*0b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h" 28*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 29*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 30*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 31*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric using namespace llvm; 34*0b57cec5SDimitry Andric 35*0b57cec5SDimitry Andric #define DEBUG_TYPE "ppc-tls-dynamic-call" 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric namespace { 38*0b57cec5SDimitry Andric struct PPCTLSDynamicCall : public MachineFunctionPass { 39*0b57cec5SDimitry Andric static char ID; 40*0b57cec5SDimitry Andric PPCTLSDynamicCall() : MachineFunctionPass(ID) { 41*0b57cec5SDimitry Andric initializePPCTLSDynamicCallPass(*PassRegistry::getPassRegistry()); 42*0b57cec5SDimitry Andric } 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric const PPCInstrInfo *TII; 45*0b57cec5SDimitry Andric LiveIntervals *LIS; 46*0b57cec5SDimitry Andric 47*0b57cec5SDimitry Andric protected: 48*0b57cec5SDimitry Andric bool processBlock(MachineBasicBlock &MBB) { 49*0b57cec5SDimitry Andric bool Changed = false; 50*0b57cec5SDimitry Andric bool NeedFence = true; 51*0b57cec5SDimitry Andric bool Is64Bit = MBB.getParent()->getSubtarget<PPCSubtarget>().isPPC64(); 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end(); 54*0b57cec5SDimitry Andric I != IE;) { 55*0b57cec5SDimitry Andric MachineInstr &MI = *I; 56*0b57cec5SDimitry Andric 57*0b57cec5SDimitry Andric if (MI.getOpcode() != PPC::ADDItlsgdLADDR && 58*0b57cec5SDimitry Andric MI.getOpcode() != PPC::ADDItlsldLADDR && 59*0b57cec5SDimitry Andric MI.getOpcode() != PPC::ADDItlsgdLADDR32 && 60*0b57cec5SDimitry Andric MI.getOpcode() != PPC::ADDItlsldLADDR32) { 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric // Although we create ADJCALLSTACKDOWN and ADJCALLSTACKUP 63*0b57cec5SDimitry Andric // as scheduling fences, we skip creating fences if we already 64*0b57cec5SDimitry Andric // have existing ADJCALLSTACKDOWN/UP to avoid nesting, 65*0b57cec5SDimitry Andric // which causes verification error with -verify-machineinstrs. 66*0b57cec5SDimitry Andric if (MI.getOpcode() == PPC::ADJCALLSTACKDOWN) 67*0b57cec5SDimitry Andric NeedFence = false; 68*0b57cec5SDimitry Andric else if (MI.getOpcode() == PPC::ADJCALLSTACKUP) 69*0b57cec5SDimitry Andric NeedFence = true; 70*0b57cec5SDimitry Andric 71*0b57cec5SDimitry Andric ++I; 72*0b57cec5SDimitry Andric continue; 73*0b57cec5SDimitry Andric } 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "TLS Dynamic Call Fixup:\n " << MI); 76*0b57cec5SDimitry Andric 77*0b57cec5SDimitry Andric unsigned OutReg = MI.getOperand(0).getReg(); 78*0b57cec5SDimitry Andric unsigned InReg = MI.getOperand(1).getReg(); 79*0b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 80*0b57cec5SDimitry Andric unsigned GPR3 = Is64Bit ? PPC::X3 : PPC::R3; 81*0b57cec5SDimitry Andric unsigned Opc1, Opc2; 82*0b57cec5SDimitry Andric const unsigned OrigRegs[] = {OutReg, InReg, GPR3}; 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric switch (MI.getOpcode()) { 85*0b57cec5SDimitry Andric default: 86*0b57cec5SDimitry Andric llvm_unreachable("Opcode inconsistency error"); 87*0b57cec5SDimitry Andric case PPC::ADDItlsgdLADDR: 88*0b57cec5SDimitry Andric Opc1 = PPC::ADDItlsgdL; 89*0b57cec5SDimitry Andric Opc2 = PPC::GETtlsADDR; 90*0b57cec5SDimitry Andric break; 91*0b57cec5SDimitry Andric case PPC::ADDItlsldLADDR: 92*0b57cec5SDimitry Andric Opc1 = PPC::ADDItlsldL; 93*0b57cec5SDimitry Andric Opc2 = PPC::GETtlsldADDR; 94*0b57cec5SDimitry Andric break; 95*0b57cec5SDimitry Andric case PPC::ADDItlsgdLADDR32: 96*0b57cec5SDimitry Andric Opc1 = PPC::ADDItlsgdL32; 97*0b57cec5SDimitry Andric Opc2 = PPC::GETtlsADDR32; 98*0b57cec5SDimitry Andric break; 99*0b57cec5SDimitry Andric case PPC::ADDItlsldLADDR32: 100*0b57cec5SDimitry Andric Opc1 = PPC::ADDItlsldL32; 101*0b57cec5SDimitry Andric Opc2 = PPC::GETtlsldADDR32; 102*0b57cec5SDimitry Andric break; 103*0b57cec5SDimitry Andric } 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric // We create ADJCALLSTACKUP and ADJCALLSTACKDOWN around _tls_get_addr 106*0b57cec5SDimitry Andric // as scheduling fence to avoid it is scheduled before 107*0b57cec5SDimitry Andric // mflr in the prologue and the address in LR is clobbered (PR25839). 108*0b57cec5SDimitry Andric // We don't really need to save data to the stack - the clobbered 109*0b57cec5SDimitry Andric // registers are already saved when the SDNode (e.g. PPCaddiTlsgdLAddr) 110*0b57cec5SDimitry Andric // gets translated to the pseudo instruction (e.g. ADDItlsgdLADDR). 111*0b57cec5SDimitry Andric if (NeedFence) 112*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII->get(PPC::ADJCALLSTACKDOWN)).addImm(0) 113*0b57cec5SDimitry Andric .addImm(0); 114*0b57cec5SDimitry Andric 115*0b57cec5SDimitry Andric // Expand into two ops built prior to the existing instruction. 116*0b57cec5SDimitry Andric MachineInstr *Addi = BuildMI(MBB, I, DL, TII->get(Opc1), GPR3) 117*0b57cec5SDimitry Andric .addReg(InReg); 118*0b57cec5SDimitry Andric Addi->addOperand(MI.getOperand(2)); 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric // The ADDItls* instruction is the first instruction in the 121*0b57cec5SDimitry Andric // repair range. 122*0b57cec5SDimitry Andric MachineBasicBlock::iterator First = I; 123*0b57cec5SDimitry Andric --First; 124*0b57cec5SDimitry Andric 125*0b57cec5SDimitry Andric MachineInstr *Call = (BuildMI(MBB, I, DL, TII->get(Opc2), GPR3) 126*0b57cec5SDimitry Andric .addReg(GPR3)); 127*0b57cec5SDimitry Andric Call->addOperand(MI.getOperand(3)); 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric if (NeedFence) 130*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII->get(PPC::ADJCALLSTACKUP)).addImm(0).addImm(0); 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII->get(TargetOpcode::COPY), OutReg) 133*0b57cec5SDimitry Andric .addReg(GPR3); 134*0b57cec5SDimitry Andric 135*0b57cec5SDimitry Andric // The COPY is the last instruction in the repair range. 136*0b57cec5SDimitry Andric MachineBasicBlock::iterator Last = I; 137*0b57cec5SDimitry Andric --Last; 138*0b57cec5SDimitry Andric 139*0b57cec5SDimitry Andric // Move past the original instruction and remove it. 140*0b57cec5SDimitry Andric ++I; 141*0b57cec5SDimitry Andric MI.removeFromParent(); 142*0b57cec5SDimitry Andric 143*0b57cec5SDimitry Andric // Repair the live intervals. 144*0b57cec5SDimitry Andric LIS->repairIntervalsInRange(&MBB, First, Last, OrigRegs); 145*0b57cec5SDimitry Andric Changed = true; 146*0b57cec5SDimitry Andric } 147*0b57cec5SDimitry Andric 148*0b57cec5SDimitry Andric return Changed; 149*0b57cec5SDimitry Andric } 150*0b57cec5SDimitry Andric 151*0b57cec5SDimitry Andric public: 152*0b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override { 153*0b57cec5SDimitry Andric TII = MF.getSubtarget<PPCSubtarget>().getInstrInfo(); 154*0b57cec5SDimitry Andric LIS = &getAnalysis<LiveIntervals>(); 155*0b57cec5SDimitry Andric 156*0b57cec5SDimitry Andric bool Changed = false; 157*0b57cec5SDimitry Andric 158*0b57cec5SDimitry Andric for (MachineFunction::iterator I = MF.begin(); I != MF.end();) { 159*0b57cec5SDimitry Andric MachineBasicBlock &B = *I++; 160*0b57cec5SDimitry Andric if (processBlock(B)) 161*0b57cec5SDimitry Andric Changed = true; 162*0b57cec5SDimitry Andric } 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric return Changed; 165*0b57cec5SDimitry Andric } 166*0b57cec5SDimitry Andric 167*0b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 168*0b57cec5SDimitry Andric AU.addRequired<LiveIntervals>(); 169*0b57cec5SDimitry Andric AU.addPreserved<LiveIntervals>(); 170*0b57cec5SDimitry Andric AU.addRequired<SlotIndexes>(); 171*0b57cec5SDimitry Andric AU.addPreserved<SlotIndexes>(); 172*0b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 173*0b57cec5SDimitry Andric } 174*0b57cec5SDimitry Andric }; 175*0b57cec5SDimitry Andric } 176*0b57cec5SDimitry Andric 177*0b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(PPCTLSDynamicCall, DEBUG_TYPE, 178*0b57cec5SDimitry Andric "PowerPC TLS Dynamic Call Fixup", false, false) 179*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveIntervals) 180*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(SlotIndexes) 181*0b57cec5SDimitry Andric INITIALIZE_PASS_END(PPCTLSDynamicCall, DEBUG_TYPE, 182*0b57cec5SDimitry Andric "PowerPC TLS Dynamic Call Fixup", false, false) 183*0b57cec5SDimitry Andric 184*0b57cec5SDimitry Andric char PPCTLSDynamicCall::ID = 0; 185*0b57cec5SDimitry Andric FunctionPass* 186*0b57cec5SDimitry Andric llvm::createPPCTLSDynamicCallPass() { return new PPCTLSDynamicCall(); } 187