1235633Sdim//===-- SparcFrameLowering.cpp - Sparc Frame Information ------------------===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file contains the Sparc implementation of TargetFrameLowering class. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14218885Sdim#include "SparcFrameLowering.h" 15218885Sdim#include "SparcInstrInfo.h" 16218885Sdim#include "SparcMachineFunctionInfo.h" 17218885Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 18218885Sdim#include "llvm/CodeGen/MachineFunction.h" 19218885Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 20218885Sdim#include "llvm/CodeGen/MachineModuleInfo.h" 21218885Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 22252723Sdim#include "llvm/IR/DataLayout.h" 23252723Sdim#include "llvm/IR/Function.h" 24252723Sdim#include "llvm/Support/CommandLine.h" 25218885Sdim#include "llvm/Target/TargetOptions.h" 26218885Sdim 27218885Sdimusing namespace llvm; 28218885Sdim 29263509Sdimstatic cl::opt<bool> 30263509SdimDisableLeafProc("disable-sparc-leaf-proc", 31263509Sdim cl::init(false), 32263509Sdim cl::desc("Disable Sparc leaf procedure optimization."), 33263509Sdim cl::Hidden); 34263509Sdim 35263509Sdim 36263509Sdimvoid SparcFrameLowering::emitSPAdjustment(MachineFunction &MF, 37263509Sdim MachineBasicBlock &MBB, 38263509Sdim MachineBasicBlock::iterator MBBI, 39263509Sdim int NumBytes, 40263509Sdim unsigned ADDrr, 41263509Sdim unsigned ADDri) const { 42263509Sdim 43263509Sdim DebugLoc dl = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc(); 44263509Sdim const SparcInstrInfo &TII = 45263509Sdim *static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo()); 46263509Sdim 47263509Sdim if (NumBytes >= -4096 && NumBytes < 4096) { 48263509Sdim BuildMI(MBB, MBBI, dl, TII.get(ADDri), SP::O6) 49263509Sdim .addReg(SP::O6).addImm(NumBytes); 50263509Sdim return; 51263509Sdim } 52263509Sdim 53263509Sdim // Emit this the hard way. This clobbers G1 which we always know is 54263509Sdim // available here. 55263509Sdim if (NumBytes >= 0) { 56263509Sdim // Emit nonnegative numbers with sethi + or. 57263509Sdim // sethi %hi(NumBytes), %g1 58263509Sdim // or %g1, %lo(NumBytes), %g1 59263509Sdim // add %sp, %g1, %sp 60263509Sdim BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1) 61263509Sdim .addImm(HI22(NumBytes)); 62263509Sdim BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1) 63263509Sdim .addReg(SP::G1).addImm(LO10(NumBytes)); 64263509Sdim BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6) 65263509Sdim .addReg(SP::O6).addReg(SP::G1); 66263509Sdim return ; 67263509Sdim } 68263509Sdim 69263509Sdim // Emit negative numbers with sethi + xor. 70263509Sdim // sethi %hix(NumBytes), %g1 71263509Sdim // xor %g1, %lox(NumBytes), %g1 72263509Sdim // add %sp, %g1, %sp 73263509Sdim BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1) 74263509Sdim .addImm(HIX22(NumBytes)); 75263509Sdim BuildMI(MBB, MBBI, dl, TII.get(SP::XORri), SP::G1) 76263509Sdim .addReg(SP::G1).addImm(LOX10(NumBytes)); 77263509Sdim BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6) 78263509Sdim .addReg(SP::O6).addReg(SP::G1); 79263509Sdim} 80263509Sdim 81218885Sdimvoid SparcFrameLowering::emitPrologue(MachineFunction &MF) const { 82263509Sdim SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 83263509Sdim 84218885Sdim MachineBasicBlock &MBB = MF.front(); 85218885Sdim MachineFrameInfo *MFI = MF.getFrameInfo(); 86218885Sdim const SparcInstrInfo &TII = 87218885Sdim *static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo()); 88218885Sdim MachineBasicBlock::iterator MBBI = MBB.begin(); 89218885Sdim DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 90218885Sdim 91218885Sdim // Get the number of bytes to allocate from the FrameInfo 92218885Sdim int NumBytes = (int) MFI->getStackSize(); 93218885Sdim 94263509Sdim unsigned SAVEri = SP::SAVEri; 95263509Sdim unsigned SAVErr = SP::SAVErr; 96263509Sdim if (FuncInfo->isLeafProc()) { 97263509Sdim if (NumBytes == 0) 98263509Sdim return; 99263509Sdim SAVEri = SP::ADDri; 100263509Sdim SAVErr = SP::ADDrr; 101252723Sdim } 102263509Sdim NumBytes = - SubTarget.getAdjustedFrameSize(NumBytes); 103263509Sdim emitSPAdjustment(MF, MBB, MBBI, NumBytes, SAVErr, SAVEri); 104218885Sdim 105263509Sdim MachineModuleInfo &MMI = MF.getMMI(); 106263509Sdim const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); 107263509Sdim MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol(); 108263509Sdim BuildMI(MBB, MBBI, dl, TII.get(SP::PROLOG_LABEL)).addSym(FrameLabel); 109263509Sdim 110263509Sdim unsigned regFP = MRI->getDwarfRegNum(SP::I6, true); 111263509Sdim 112263509Sdim // Emit ".cfi_def_cfa_register 30". 113263509Sdim MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister(FrameLabel, 114263509Sdim regFP)); 115263509Sdim // Emit ".cfi_window_save". 116263509Sdim MMI.addFrameInst(MCCFIInstruction::createWindowSave(FrameLabel)); 117263509Sdim 118263509Sdim unsigned regInRA = MRI->getDwarfRegNum(SP::I7, true); 119263509Sdim unsigned regOutRA = MRI->getDwarfRegNum(SP::O7, true); 120263509Sdim // Emit ".cfi_register 15, 31". 121263509Sdim MMI.addFrameInst(MCCFIInstruction::createRegister(FrameLabel, 122263509Sdim regOutRA, 123263509Sdim regInRA)); 124218885Sdim} 125218885Sdim 126252723Sdimvoid SparcFrameLowering:: 127252723SdimeliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 128252723Sdim MachineBasicBlock::iterator I) const { 129252723Sdim if (!hasReservedCallFrame(MF)) { 130252723Sdim MachineInstr &MI = *I; 131252723Sdim int Size = MI.getOperand(0).getImm(); 132252723Sdim if (MI.getOpcode() == SP::ADJCALLSTACKDOWN) 133252723Sdim Size = -Size; 134263509Sdim 135252723Sdim if (Size) 136263509Sdim emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri); 137252723Sdim } 138252723Sdim MBB.erase(I); 139252723Sdim} 140252723Sdim 141252723Sdim 142218885Sdimvoid SparcFrameLowering::emitEpilogue(MachineFunction &MF, 143218885Sdim MachineBasicBlock &MBB) const { 144263509Sdim SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 145218885Sdim MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 146218885Sdim const SparcInstrInfo &TII = 147218885Sdim *static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo()); 148218885Sdim DebugLoc dl = MBBI->getDebugLoc(); 149218885Sdim assert(MBBI->getOpcode() == SP::RETL && 150218885Sdim "Can only put epilog before 'retl' instruction!"); 151263509Sdim if (!FuncInfo->isLeafProc()) { 152263509Sdim BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0) 153263509Sdim .addReg(SP::G0); 154263509Sdim return; 155263509Sdim } 156263509Sdim MachineFrameInfo *MFI = MF.getFrameInfo(); 157263509Sdim 158263509Sdim int NumBytes = (int) MFI->getStackSize(); 159263509Sdim if (NumBytes == 0) 160263509Sdim return; 161263509Sdim 162263509Sdim NumBytes = SubTarget.getAdjustedFrameSize(NumBytes); 163263509Sdim emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri); 164218885Sdim} 165263509Sdim 166263509Sdimbool SparcFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { 167263509Sdim // Reserve call frame if there are no variable sized objects on the stack. 168263509Sdim return !MF.getFrameInfo()->hasVarSizedObjects(); 169263509Sdim} 170263509Sdim 171263509Sdim// hasFP - Return true if the specified function should have a dedicated frame 172263509Sdim// pointer register. This is true if the function has variable sized allocas or 173263509Sdim// if frame pointer elimination is disabled. 174263509Sdimbool SparcFrameLowering::hasFP(const MachineFunction &MF) const { 175263509Sdim const MachineFrameInfo *MFI = MF.getFrameInfo(); 176263509Sdim return MF.getTarget().Options.DisableFramePointerElim(MF) || 177263509Sdim MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken(); 178263509Sdim} 179263509Sdim 180263509Sdim 181263509Sdimstatic bool LLVM_ATTRIBUTE_UNUSED verifyLeafProcRegUse(MachineRegisterInfo *MRI) 182263509Sdim{ 183263509Sdim 184263509Sdim for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) 185263509Sdim if (MRI->isPhysRegUsed(reg)) 186263509Sdim return false; 187263509Sdim 188263509Sdim for (unsigned reg = SP::L0; reg <= SP::L7; ++reg) 189263509Sdim if (MRI->isPhysRegUsed(reg)) 190263509Sdim return false; 191263509Sdim 192263509Sdim return true; 193263509Sdim} 194263509Sdim 195263509Sdimbool SparcFrameLowering::isLeafProc(MachineFunction &MF) const 196263509Sdim{ 197263509Sdim 198263509Sdim MachineRegisterInfo &MRI = MF.getRegInfo(); 199263509Sdim MachineFrameInfo *MFI = MF.getFrameInfo(); 200263509Sdim 201263509Sdim return !(MFI->hasCalls() // has calls 202263509Sdim || MRI.isPhysRegUsed(SP::L0) // Too many registers needed 203263509Sdim || MRI.isPhysRegUsed(SP::O6) // %SP is used 204263509Sdim || hasFP(MF)); // need %FP 205263509Sdim} 206263509Sdim 207263509Sdimvoid SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const { 208263509Sdim 209263509Sdim MachineRegisterInfo &MRI = MF.getRegInfo(); 210263509Sdim 211263509Sdim // Remap %i[0-7] to %o[0-7]. 212263509Sdim for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) { 213263509Sdim if (!MRI.isPhysRegUsed(reg)) 214263509Sdim continue; 215263509Sdim unsigned mapped_reg = (reg - SP::I0 + SP::O0); 216263509Sdim assert(!MRI.isPhysRegUsed(mapped_reg)); 217263509Sdim 218263509Sdim // Replace I register with O register. 219263509Sdim MRI.replaceRegWith(reg, mapped_reg); 220263509Sdim 221263509Sdim // Mark the reg unused. 222263509Sdim MRI.setPhysRegUnused(reg); 223263509Sdim } 224263509Sdim 225263509Sdim // Rewrite MBB's Live-ins. 226263509Sdim for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); 227263509Sdim MBB != E; ++MBB) { 228263509Sdim for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) { 229263509Sdim if (!MBB->isLiveIn(reg)) 230263509Sdim continue; 231263509Sdim MBB->removeLiveIn(reg); 232263509Sdim MBB->addLiveIn(reg - SP::I0 + SP::O0); 233263509Sdim } 234263509Sdim } 235263509Sdim 236263509Sdim assert(verifyLeafProcRegUse(&MRI)); 237263509Sdim#ifdef XDEBUG 238263509Sdim MF.verify(0, "After LeafProc Remapping"); 239263509Sdim#endif 240263509Sdim} 241263509Sdim 242263509Sdimvoid SparcFrameLowering::processFunctionBeforeCalleeSavedScan 243263509Sdim (MachineFunction &MF, RegScavenger *RS) const { 244263509Sdim 245263509Sdim if (!DisableLeafProc && isLeafProc(MF)) { 246263509Sdim SparcMachineFunctionInfo *MFI = MF.getInfo<SparcMachineFunctionInfo>(); 247263509Sdim MFI->setLeafProc(true); 248263509Sdim 249263509Sdim remapRegsForLeafProc(MF); 250263509Sdim } 251263509Sdim 252263509Sdim} 253