1*0b57cec5SDimitry Andric //===-- SparcFrameLowering.cpp - Sparc Frame Information ------------------===// 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 file contains the Sparc implementation of TargetFrameLowering class. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "SparcFrameLowering.h" 14*0b57cec5SDimitry Andric #include "SparcInstrInfo.h" 15*0b57cec5SDimitry Andric #include "SparcMachineFunctionInfo.h" 16*0b57cec5SDimitry Andric #include "SparcSubtarget.h" 17*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 19*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 22*0b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 23*0b57cec5SDimitry Andric #include "llvm/IR/Function.h" 24*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 25*0b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric using namespace llvm; 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric static cl::opt<bool> 30*0b57cec5SDimitry Andric DisableLeafProc("disable-sparc-leaf-proc", 31*0b57cec5SDimitry Andric cl::init(false), 32*0b57cec5SDimitry Andric cl::desc("Disable Sparc leaf procedure optimization."), 33*0b57cec5SDimitry Andric cl::Hidden); 34*0b57cec5SDimitry Andric 35*0b57cec5SDimitry Andric SparcFrameLowering::SparcFrameLowering(const SparcSubtarget &ST) 36*0b57cec5SDimitry Andric : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 37*0b57cec5SDimitry Andric ST.is64Bit() ? 16 : 8, 0, ST.is64Bit() ? 16 : 8) {} 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF, 40*0b57cec5SDimitry Andric MachineBasicBlock &MBB, 41*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, 42*0b57cec5SDimitry Andric int NumBytes, 43*0b57cec5SDimitry Andric unsigned ADDrr, 44*0b57cec5SDimitry Andric unsigned ADDri) const { 45*0b57cec5SDimitry Andric 46*0b57cec5SDimitry Andric DebugLoc dl; 47*0b57cec5SDimitry Andric const SparcInstrInfo &TII = 48*0b57cec5SDimitry Andric *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo()); 49*0b57cec5SDimitry Andric 50*0b57cec5SDimitry Andric if (NumBytes >= -4096 && NumBytes < 4096) { 51*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ADDri), SP::O6) 52*0b57cec5SDimitry Andric .addReg(SP::O6).addImm(NumBytes); 53*0b57cec5SDimitry Andric return; 54*0b57cec5SDimitry Andric } 55*0b57cec5SDimitry Andric 56*0b57cec5SDimitry Andric // Emit this the hard way. This clobbers G1 which we always know is 57*0b57cec5SDimitry Andric // available here. 58*0b57cec5SDimitry Andric if (NumBytes >= 0) { 59*0b57cec5SDimitry Andric // Emit nonnegative numbers with sethi + or. 60*0b57cec5SDimitry Andric // sethi %hi(NumBytes), %g1 61*0b57cec5SDimitry Andric // or %g1, %lo(NumBytes), %g1 62*0b57cec5SDimitry Andric // add %sp, %g1, %sp 63*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1) 64*0b57cec5SDimitry Andric .addImm(HI22(NumBytes)); 65*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1) 66*0b57cec5SDimitry Andric .addReg(SP::G1).addImm(LO10(NumBytes)); 67*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6) 68*0b57cec5SDimitry Andric .addReg(SP::O6).addReg(SP::G1); 69*0b57cec5SDimitry Andric return ; 70*0b57cec5SDimitry Andric } 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andric // Emit negative numbers with sethi + xor. 73*0b57cec5SDimitry Andric // sethi %hix(NumBytes), %g1 74*0b57cec5SDimitry Andric // xor %g1, %lox(NumBytes), %g1 75*0b57cec5SDimitry Andric // add %sp, %g1, %sp 76*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1) 77*0b57cec5SDimitry Andric .addImm(HIX22(NumBytes)); 78*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::XORri), SP::G1) 79*0b57cec5SDimitry Andric .addReg(SP::G1).addImm(LOX10(NumBytes)); 80*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6) 81*0b57cec5SDimitry Andric .addReg(SP::O6).addReg(SP::G1); 82*0b57cec5SDimitry Andric } 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric void SparcFrameLowering::emitPrologue(MachineFunction &MF, 85*0b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 86*0b57cec5SDimitry Andric SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); 89*0b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 90*0b57cec5SDimitry Andric const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>(); 91*0b57cec5SDimitry Andric const SparcInstrInfo &TII = 92*0b57cec5SDimitry Andric *static_cast<const SparcInstrInfo *>(Subtarget.getInstrInfo()); 93*0b57cec5SDimitry Andric const SparcRegisterInfo &RegInfo = 94*0b57cec5SDimitry Andric *static_cast<const SparcRegisterInfo *>(Subtarget.getRegisterInfo()); 95*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(); 96*0b57cec5SDimitry Andric // Debug location must be unknown since the first debug location is used 97*0b57cec5SDimitry Andric // to determine the end of the prologue. 98*0b57cec5SDimitry Andric DebugLoc dl; 99*0b57cec5SDimitry Andric bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF); 100*0b57cec5SDimitry Andric 101*0b57cec5SDimitry Andric // FIXME: unfortunately, returning false from canRealignStack 102*0b57cec5SDimitry Andric // actually just causes needsStackRealignment to return false, 103*0b57cec5SDimitry Andric // rather than reporting an error, as would be sensible. This is 104*0b57cec5SDimitry Andric // poor, but fixing that bogosity is going to be a large project. 105*0b57cec5SDimitry Andric // For now, just see if it's lied, and report an error here. 106*0b57cec5SDimitry Andric if (!NeedsStackRealignment && MFI.getMaxAlignment() > getStackAlignment()) 107*0b57cec5SDimitry Andric report_fatal_error("Function \"" + Twine(MF.getName()) + "\" required " 108*0b57cec5SDimitry Andric "stack re-alignment, but LLVM couldn't handle it " 109*0b57cec5SDimitry Andric "(probably because it has a dynamic alloca)."); 110*0b57cec5SDimitry Andric 111*0b57cec5SDimitry Andric // Get the number of bytes to allocate from the FrameInfo 112*0b57cec5SDimitry Andric int NumBytes = (int) MFI.getStackSize(); 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric unsigned SAVEri = SP::SAVEri; 115*0b57cec5SDimitry Andric unsigned SAVErr = SP::SAVErr; 116*0b57cec5SDimitry Andric if (FuncInfo->isLeafProc()) { 117*0b57cec5SDimitry Andric if (NumBytes == 0) 118*0b57cec5SDimitry Andric return; 119*0b57cec5SDimitry Andric SAVEri = SP::ADDri; 120*0b57cec5SDimitry Andric SAVErr = SP::ADDrr; 121*0b57cec5SDimitry Andric } 122*0b57cec5SDimitry Andric 123*0b57cec5SDimitry Andric // The SPARC ABI is a bit odd in that it requires a reserved 92-byte 124*0b57cec5SDimitry Andric // (128 in v9) area in the user's stack, starting at %sp. Thus, the 125*0b57cec5SDimitry Andric // first part of the stack that can actually be used is located at 126*0b57cec5SDimitry Andric // %sp + 92. 127*0b57cec5SDimitry Andric // 128*0b57cec5SDimitry Andric // We therefore need to add that offset to the total stack size 129*0b57cec5SDimitry Andric // after all the stack objects are placed by 130*0b57cec5SDimitry Andric // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack needs to be 131*0b57cec5SDimitry Andric // aligned *after* the extra size is added, we need to disable 132*0b57cec5SDimitry Andric // calculateFrameObjectOffsets's built-in stack alignment, by having 133*0b57cec5SDimitry Andric // targetHandlesStackFrameRounding return true. 134*0b57cec5SDimitry Andric 135*0b57cec5SDimitry Andric 136*0b57cec5SDimitry Andric // Add the extra call frame stack size, if needed. (This is the same 137*0b57cec5SDimitry Andric // code as in PrologEpilogInserter, but also gets disabled by 138*0b57cec5SDimitry Andric // targetHandlesStackFrameRounding) 139*0b57cec5SDimitry Andric if (MFI.adjustsStack() && hasReservedCallFrame(MF)) 140*0b57cec5SDimitry Andric NumBytes += MFI.getMaxCallFrameSize(); 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric // Adds the SPARC subtarget-specific spill area to the stack 143*0b57cec5SDimitry Andric // size. Also ensures target-required alignment. 144*0b57cec5SDimitry Andric NumBytes = Subtarget.getAdjustedFrameSize(NumBytes); 145*0b57cec5SDimitry Andric 146*0b57cec5SDimitry Andric // Finally, ensure that the size is sufficiently aligned for the 147*0b57cec5SDimitry Andric // data on the stack. 148*0b57cec5SDimitry Andric if (MFI.getMaxAlignment() > 0) { 149*0b57cec5SDimitry Andric NumBytes = alignTo(NumBytes, MFI.getMaxAlignment()); 150*0b57cec5SDimitry Andric } 151*0b57cec5SDimitry Andric 152*0b57cec5SDimitry Andric // Update stack size with corrected value. 153*0b57cec5SDimitry Andric MFI.setStackSize(NumBytes); 154*0b57cec5SDimitry Andric 155*0b57cec5SDimitry Andric emitSPAdjustment(MF, MBB, MBBI, -NumBytes, SAVErr, SAVEri); 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric unsigned regFP = RegInfo.getDwarfRegNum(SP::I6, true); 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric // Emit ".cfi_def_cfa_register 30". 160*0b57cec5SDimitry Andric unsigned CFIIndex = 161*0b57cec5SDimitry Andric MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, regFP)); 162*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 163*0b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andric // Emit ".cfi_window_save". 166*0b57cec5SDimitry Andric CFIIndex = MF.addFrameInst(MCCFIInstruction::createWindowSave(nullptr)); 167*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 168*0b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric unsigned regInRA = RegInfo.getDwarfRegNum(SP::I7, true); 171*0b57cec5SDimitry Andric unsigned regOutRA = RegInfo.getDwarfRegNum(SP::O7, true); 172*0b57cec5SDimitry Andric // Emit ".cfi_register 15, 31". 173*0b57cec5SDimitry Andric CFIIndex = MF.addFrameInst( 174*0b57cec5SDimitry Andric MCCFIInstruction::createRegister(nullptr, regOutRA, regInRA)); 175*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 176*0b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 177*0b57cec5SDimitry Andric 178*0b57cec5SDimitry Andric if (NeedsStackRealignment) { 179*0b57cec5SDimitry Andric int64_t Bias = Subtarget.getStackPointerBias(); 180*0b57cec5SDimitry Andric unsigned regUnbiased; 181*0b57cec5SDimitry Andric if (Bias) { 182*0b57cec5SDimitry Andric // This clobbers G1 which we always know is available here. 183*0b57cec5SDimitry Andric regUnbiased = SP::G1; 184*0b57cec5SDimitry Andric // add %o6, BIAS, %g1 185*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), regUnbiased) 186*0b57cec5SDimitry Andric .addReg(SP::O6).addImm(Bias); 187*0b57cec5SDimitry Andric } else 188*0b57cec5SDimitry Andric regUnbiased = SP::O6; 189*0b57cec5SDimitry Andric 190*0b57cec5SDimitry Andric // andn %regUnbiased, MaxAlign-1, %regUnbiased 191*0b57cec5SDimitry Andric int MaxAlign = MFI.getMaxAlignment(); 192*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::ANDNri), regUnbiased) 193*0b57cec5SDimitry Andric .addReg(regUnbiased).addImm(MaxAlign - 1); 194*0b57cec5SDimitry Andric 195*0b57cec5SDimitry Andric if (Bias) { 196*0b57cec5SDimitry Andric // add %g1, -BIAS, %o6 197*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), SP::O6) 198*0b57cec5SDimitry Andric .addReg(regUnbiased).addImm(-Bias); 199*0b57cec5SDimitry Andric } 200*0b57cec5SDimitry Andric } 201*0b57cec5SDimitry Andric } 202*0b57cec5SDimitry Andric 203*0b57cec5SDimitry Andric MachineBasicBlock::iterator SparcFrameLowering:: 204*0b57cec5SDimitry Andric eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 205*0b57cec5SDimitry Andric MachineBasicBlock::iterator I) const { 206*0b57cec5SDimitry Andric if (!hasReservedCallFrame(MF)) { 207*0b57cec5SDimitry Andric MachineInstr &MI = *I; 208*0b57cec5SDimitry Andric int Size = MI.getOperand(0).getImm(); 209*0b57cec5SDimitry Andric if (MI.getOpcode() == SP::ADJCALLSTACKDOWN) 210*0b57cec5SDimitry Andric Size = -Size; 211*0b57cec5SDimitry Andric 212*0b57cec5SDimitry Andric if (Size) 213*0b57cec5SDimitry Andric emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri); 214*0b57cec5SDimitry Andric } 215*0b57cec5SDimitry Andric return MBB.erase(I); 216*0b57cec5SDimitry Andric } 217*0b57cec5SDimitry Andric 218*0b57cec5SDimitry Andric 219*0b57cec5SDimitry Andric void SparcFrameLowering::emitEpilogue(MachineFunction &MF, 220*0b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 221*0b57cec5SDimitry Andric SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 222*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 223*0b57cec5SDimitry Andric const SparcInstrInfo &TII = 224*0b57cec5SDimitry Andric *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo()); 225*0b57cec5SDimitry Andric DebugLoc dl = MBBI->getDebugLoc(); 226*0b57cec5SDimitry Andric assert(MBBI->getOpcode() == SP::RETL && 227*0b57cec5SDimitry Andric "Can only put epilog before 'retl' instruction!"); 228*0b57cec5SDimitry Andric if (!FuncInfo->isLeafProc()) { 229*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0) 230*0b57cec5SDimitry Andric .addReg(SP::G0); 231*0b57cec5SDimitry Andric return; 232*0b57cec5SDimitry Andric } 233*0b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 234*0b57cec5SDimitry Andric 235*0b57cec5SDimitry Andric int NumBytes = (int) MFI.getStackSize(); 236*0b57cec5SDimitry Andric if (NumBytes == 0) 237*0b57cec5SDimitry Andric return; 238*0b57cec5SDimitry Andric 239*0b57cec5SDimitry Andric emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri); 240*0b57cec5SDimitry Andric } 241*0b57cec5SDimitry Andric 242*0b57cec5SDimitry Andric bool SparcFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { 243*0b57cec5SDimitry Andric // Reserve call frame if there are no variable sized objects on the stack. 244*0b57cec5SDimitry Andric return !MF.getFrameInfo().hasVarSizedObjects(); 245*0b57cec5SDimitry Andric } 246*0b57cec5SDimitry Andric 247*0b57cec5SDimitry Andric // hasFP - Return true if the specified function should have a dedicated frame 248*0b57cec5SDimitry Andric // pointer register. This is true if the function has variable sized allocas or 249*0b57cec5SDimitry Andric // if frame pointer elimination is disabled. 250*0b57cec5SDimitry Andric bool SparcFrameLowering::hasFP(const MachineFunction &MF) const { 251*0b57cec5SDimitry Andric const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); 252*0b57cec5SDimitry Andric 253*0b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 254*0b57cec5SDimitry Andric return MF.getTarget().Options.DisableFramePointerElim(MF) || 255*0b57cec5SDimitry Andric RegInfo->needsStackRealignment(MF) || 256*0b57cec5SDimitry Andric MFI.hasVarSizedObjects() || 257*0b57cec5SDimitry Andric MFI.isFrameAddressTaken(); 258*0b57cec5SDimitry Andric } 259*0b57cec5SDimitry Andric 260*0b57cec5SDimitry Andric 261*0b57cec5SDimitry Andric int SparcFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, 262*0b57cec5SDimitry Andric unsigned &FrameReg) const { 263*0b57cec5SDimitry Andric const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>(); 264*0b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 265*0b57cec5SDimitry Andric const SparcRegisterInfo *RegInfo = Subtarget.getRegisterInfo(); 266*0b57cec5SDimitry Andric const SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 267*0b57cec5SDimitry Andric bool isFixed = MFI.isFixedObjectIndex(FI); 268*0b57cec5SDimitry Andric 269*0b57cec5SDimitry Andric // Addressable stack objects are accessed using neg. offsets from 270*0b57cec5SDimitry Andric // %fp, or positive offsets from %sp. 271*0b57cec5SDimitry Andric bool UseFP; 272*0b57cec5SDimitry Andric 273*0b57cec5SDimitry Andric // Sparc uses FP-based references in general, even when "hasFP" is 274*0b57cec5SDimitry Andric // false. That function is rather a misnomer, because %fp is 275*0b57cec5SDimitry Andric // actually always available, unless isLeafProc. 276*0b57cec5SDimitry Andric if (FuncInfo->isLeafProc()) { 277*0b57cec5SDimitry Andric // If there's a leaf proc, all offsets need to be %sp-based, 278*0b57cec5SDimitry Andric // because we haven't caused %fp to actually point to our frame. 279*0b57cec5SDimitry Andric UseFP = false; 280*0b57cec5SDimitry Andric } else if (isFixed) { 281*0b57cec5SDimitry Andric // Otherwise, argument access should always use %fp. 282*0b57cec5SDimitry Andric UseFP = true; 283*0b57cec5SDimitry Andric } else if (RegInfo->needsStackRealignment(MF)) { 284*0b57cec5SDimitry Andric // If there is dynamic stack realignment, all local object 285*0b57cec5SDimitry Andric // references need to be via %sp, to take account of the 286*0b57cec5SDimitry Andric // re-alignment. 287*0b57cec5SDimitry Andric UseFP = false; 288*0b57cec5SDimitry Andric } else { 289*0b57cec5SDimitry Andric // Finally, default to using %fp. 290*0b57cec5SDimitry Andric UseFP = true; 291*0b57cec5SDimitry Andric } 292*0b57cec5SDimitry Andric 293*0b57cec5SDimitry Andric int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI) + 294*0b57cec5SDimitry Andric Subtarget.getStackPointerBias(); 295*0b57cec5SDimitry Andric 296*0b57cec5SDimitry Andric if (UseFP) { 297*0b57cec5SDimitry Andric FrameReg = RegInfo->getFrameRegister(MF); 298*0b57cec5SDimitry Andric return FrameOffset; 299*0b57cec5SDimitry Andric } else { 300*0b57cec5SDimitry Andric FrameReg = SP::O6; // %sp 301*0b57cec5SDimitry Andric return FrameOffset + MF.getFrameInfo().getStackSize(); 302*0b57cec5SDimitry Andric } 303*0b57cec5SDimitry Andric } 304*0b57cec5SDimitry Andric 305*0b57cec5SDimitry Andric static bool LLVM_ATTRIBUTE_UNUSED verifyLeafProcRegUse(MachineRegisterInfo *MRI) 306*0b57cec5SDimitry Andric { 307*0b57cec5SDimitry Andric 308*0b57cec5SDimitry Andric for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) 309*0b57cec5SDimitry Andric if (MRI->isPhysRegUsed(reg)) 310*0b57cec5SDimitry Andric return false; 311*0b57cec5SDimitry Andric 312*0b57cec5SDimitry Andric for (unsigned reg = SP::L0; reg <= SP::L7; ++reg) 313*0b57cec5SDimitry Andric if (MRI->isPhysRegUsed(reg)) 314*0b57cec5SDimitry Andric return false; 315*0b57cec5SDimitry Andric 316*0b57cec5SDimitry Andric return true; 317*0b57cec5SDimitry Andric } 318*0b57cec5SDimitry Andric 319*0b57cec5SDimitry Andric bool SparcFrameLowering::isLeafProc(MachineFunction &MF) const 320*0b57cec5SDimitry Andric { 321*0b57cec5SDimitry Andric 322*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 323*0b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 324*0b57cec5SDimitry Andric 325*0b57cec5SDimitry Andric return !(MFI.hasCalls() // has calls 326*0b57cec5SDimitry Andric || MRI.isPhysRegUsed(SP::L0) // Too many registers needed 327*0b57cec5SDimitry Andric || MRI.isPhysRegUsed(SP::O6) // %sp is used 328*0b57cec5SDimitry Andric || hasFP(MF)); // need %fp 329*0b57cec5SDimitry Andric } 330*0b57cec5SDimitry Andric 331*0b57cec5SDimitry Andric void SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const { 332*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 333*0b57cec5SDimitry Andric // Remap %i[0-7] to %o[0-7]. 334*0b57cec5SDimitry Andric for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) { 335*0b57cec5SDimitry Andric if (!MRI.isPhysRegUsed(reg)) 336*0b57cec5SDimitry Andric continue; 337*0b57cec5SDimitry Andric 338*0b57cec5SDimitry Andric unsigned mapped_reg = reg - SP::I0 + SP::O0; 339*0b57cec5SDimitry Andric 340*0b57cec5SDimitry Andric // Replace I register with O register. 341*0b57cec5SDimitry Andric MRI.replaceRegWith(reg, mapped_reg); 342*0b57cec5SDimitry Andric 343*0b57cec5SDimitry Andric // Also replace register pair super-registers. 344*0b57cec5SDimitry Andric if ((reg - SP::I0) % 2 == 0) { 345*0b57cec5SDimitry Andric unsigned preg = (reg - SP::I0) / 2 + SP::I0_I1; 346*0b57cec5SDimitry Andric unsigned mapped_preg = preg - SP::I0_I1 + SP::O0_O1; 347*0b57cec5SDimitry Andric MRI.replaceRegWith(preg, mapped_preg); 348*0b57cec5SDimitry Andric } 349*0b57cec5SDimitry Andric } 350*0b57cec5SDimitry Andric 351*0b57cec5SDimitry Andric // Rewrite MBB's Live-ins. 352*0b57cec5SDimitry Andric for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); 353*0b57cec5SDimitry Andric MBB != E; ++MBB) { 354*0b57cec5SDimitry Andric for (unsigned reg = SP::I0_I1; reg <= SP::I6_I7; ++reg) { 355*0b57cec5SDimitry Andric if (!MBB->isLiveIn(reg)) 356*0b57cec5SDimitry Andric continue; 357*0b57cec5SDimitry Andric MBB->removeLiveIn(reg); 358*0b57cec5SDimitry Andric MBB->addLiveIn(reg - SP::I0_I1 + SP::O0_O1); 359*0b57cec5SDimitry Andric } 360*0b57cec5SDimitry Andric for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) { 361*0b57cec5SDimitry Andric if (!MBB->isLiveIn(reg)) 362*0b57cec5SDimitry Andric continue; 363*0b57cec5SDimitry Andric MBB->removeLiveIn(reg); 364*0b57cec5SDimitry Andric MBB->addLiveIn(reg - SP::I0 + SP::O0); 365*0b57cec5SDimitry Andric } 366*0b57cec5SDimitry Andric } 367*0b57cec5SDimitry Andric 368*0b57cec5SDimitry Andric assert(verifyLeafProcRegUse(&MRI)); 369*0b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 370*0b57cec5SDimitry Andric MF.verify(0, "After LeafProc Remapping"); 371*0b57cec5SDimitry Andric #endif 372*0b57cec5SDimitry Andric } 373*0b57cec5SDimitry Andric 374*0b57cec5SDimitry Andric void SparcFrameLowering::determineCalleeSaves(MachineFunction &MF, 375*0b57cec5SDimitry Andric BitVector &SavedRegs, 376*0b57cec5SDimitry Andric RegScavenger *RS) const { 377*0b57cec5SDimitry Andric TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 378*0b57cec5SDimitry Andric if (!DisableLeafProc && isLeafProc(MF)) { 379*0b57cec5SDimitry Andric SparcMachineFunctionInfo *MFI = MF.getInfo<SparcMachineFunctionInfo>(); 380*0b57cec5SDimitry Andric MFI->setLeafProc(true); 381*0b57cec5SDimitry Andric 382*0b57cec5SDimitry Andric remapRegsForLeafProc(MF); 383*0b57cec5SDimitry Andric } 384*0b57cec5SDimitry Andric 385*0b57cec5SDimitry Andric } 386