10b57cec5SDimitry Andric //===-- SparcFrameLowering.cpp - Sparc Frame Information ------------------===// 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 file contains the Sparc implementation of TargetFrameLowering class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "SparcFrameLowering.h" 140b57cec5SDimitry Andric #include "SparcInstrInfo.h" 150b57cec5SDimitry Andric #include "SparcMachineFunctionInfo.h" 160b57cec5SDimitry Andric #include "SparcSubtarget.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 220b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 230b57cec5SDimitry Andric #include "llvm/IR/Function.h" 240b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 250b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric using namespace llvm; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric static cl::opt<bool> 300b57cec5SDimitry Andric DisableLeafProc("disable-sparc-leaf-proc", 310b57cec5SDimitry Andric cl::init(false), 320b57cec5SDimitry Andric cl::desc("Disable Sparc leaf procedure optimization."), 330b57cec5SDimitry Andric cl::Hidden); 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric SparcFrameLowering::SparcFrameLowering(const SparcSubtarget &ST) 360b57cec5SDimitry Andric : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 378bcb0991SDimitry Andric ST.is64Bit() ? Align(16) : Align(8), 0, 388bcb0991SDimitry Andric ST.is64Bit() ? Align(16) : Align(8)) {} 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF, 410b57cec5SDimitry Andric MachineBasicBlock &MBB, 420b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, 430b57cec5SDimitry Andric int NumBytes, 440b57cec5SDimitry Andric unsigned ADDrr, 450b57cec5SDimitry Andric unsigned ADDri) const { 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric DebugLoc dl; 480b57cec5SDimitry Andric const SparcInstrInfo &TII = 490b57cec5SDimitry Andric *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo()); 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric if (NumBytes >= -4096 && NumBytes < 4096) { 520b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ADDri), SP::O6) 530b57cec5SDimitry Andric .addReg(SP::O6).addImm(NumBytes); 540b57cec5SDimitry Andric return; 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric // Emit this the hard way. This clobbers G1 which we always know is 580b57cec5SDimitry Andric // available here. 590b57cec5SDimitry Andric if (NumBytes >= 0) { 600b57cec5SDimitry Andric // Emit nonnegative numbers with sethi + or. 610b57cec5SDimitry Andric // sethi %hi(NumBytes), %g1 620b57cec5SDimitry Andric // or %g1, %lo(NumBytes), %g1 630b57cec5SDimitry Andric // add %sp, %g1, %sp 640b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1) 650b57cec5SDimitry Andric .addImm(HI22(NumBytes)); 660b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1) 670b57cec5SDimitry Andric .addReg(SP::G1).addImm(LO10(NumBytes)); 680b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6) 690b57cec5SDimitry Andric .addReg(SP::O6).addReg(SP::G1); 700b57cec5SDimitry Andric return ; 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric // Emit negative numbers with sethi + xor. 740b57cec5SDimitry Andric // sethi %hix(NumBytes), %g1 750b57cec5SDimitry Andric // xor %g1, %lox(NumBytes), %g1 760b57cec5SDimitry Andric // add %sp, %g1, %sp 770b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1) 780b57cec5SDimitry Andric .addImm(HIX22(NumBytes)); 790b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::XORri), SP::G1) 800b57cec5SDimitry Andric .addReg(SP::G1).addImm(LOX10(NumBytes)); 810b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6) 820b57cec5SDimitry Andric .addReg(SP::O6).addReg(SP::G1); 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric void SparcFrameLowering::emitPrologue(MachineFunction &MF, 860b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 870b57cec5SDimitry Andric SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); 900b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 910b57cec5SDimitry Andric const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>(); 920b57cec5SDimitry Andric const SparcInstrInfo &TII = 930b57cec5SDimitry Andric *static_cast<const SparcInstrInfo *>(Subtarget.getInstrInfo()); 940b57cec5SDimitry Andric const SparcRegisterInfo &RegInfo = 950b57cec5SDimitry Andric *static_cast<const SparcRegisterInfo *>(Subtarget.getRegisterInfo()); 960b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(); 970b57cec5SDimitry Andric // Debug location must be unknown since the first debug location is used 980b57cec5SDimitry Andric // to determine the end of the prologue. 990b57cec5SDimitry Andric DebugLoc dl; 1000b57cec5SDimitry Andric bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric // FIXME: unfortunately, returning false from canRealignStack 1030b57cec5SDimitry Andric // actually just causes needsStackRealignment to return false, 1040b57cec5SDimitry Andric // rather than reporting an error, as would be sensible. This is 1050b57cec5SDimitry Andric // poor, but fixing that bogosity is going to be a large project. 1060b57cec5SDimitry Andric // For now, just see if it's lied, and report an error here. 107*5ffd83dbSDimitry Andric if (!NeedsStackRealignment && MFI.getMaxAlign() > getStackAlign()) 1080b57cec5SDimitry Andric report_fatal_error("Function \"" + Twine(MF.getName()) + "\" required " 1090b57cec5SDimitry Andric "stack re-alignment, but LLVM couldn't handle it " 1100b57cec5SDimitry Andric "(probably because it has a dynamic alloca)."); 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric // Get the number of bytes to allocate from the FrameInfo 1130b57cec5SDimitry Andric int NumBytes = (int) MFI.getStackSize(); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric unsigned SAVEri = SP::SAVEri; 1160b57cec5SDimitry Andric unsigned SAVErr = SP::SAVErr; 1170b57cec5SDimitry Andric if (FuncInfo->isLeafProc()) { 1180b57cec5SDimitry Andric if (NumBytes == 0) 1190b57cec5SDimitry Andric return; 1200b57cec5SDimitry Andric SAVEri = SP::ADDri; 1210b57cec5SDimitry Andric SAVErr = SP::ADDrr; 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric // The SPARC ABI is a bit odd in that it requires a reserved 92-byte 1250b57cec5SDimitry Andric // (128 in v9) area in the user's stack, starting at %sp. Thus, the 1260b57cec5SDimitry Andric // first part of the stack that can actually be used is located at 1270b57cec5SDimitry Andric // %sp + 92. 1280b57cec5SDimitry Andric // 1290b57cec5SDimitry Andric // We therefore need to add that offset to the total stack size 1300b57cec5SDimitry Andric // after all the stack objects are placed by 1310b57cec5SDimitry Andric // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack needs to be 1320b57cec5SDimitry Andric // aligned *after* the extra size is added, we need to disable 1330b57cec5SDimitry Andric // calculateFrameObjectOffsets's built-in stack alignment, by having 1340b57cec5SDimitry Andric // targetHandlesStackFrameRounding return true. 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric // Add the extra call frame stack size, if needed. (This is the same 1380b57cec5SDimitry Andric // code as in PrologEpilogInserter, but also gets disabled by 1390b57cec5SDimitry Andric // targetHandlesStackFrameRounding) 1400b57cec5SDimitry Andric if (MFI.adjustsStack() && hasReservedCallFrame(MF)) 1410b57cec5SDimitry Andric NumBytes += MFI.getMaxCallFrameSize(); 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric // Adds the SPARC subtarget-specific spill area to the stack 1440b57cec5SDimitry Andric // size. Also ensures target-required alignment. 1450b57cec5SDimitry Andric NumBytes = Subtarget.getAdjustedFrameSize(NumBytes); 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric // Finally, ensure that the size is sufficiently aligned for the 1480b57cec5SDimitry Andric // data on the stack. 149*5ffd83dbSDimitry Andric NumBytes = alignTo(NumBytes, MFI.getMaxAlign()); 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric // Update stack size with corrected value. 1520b57cec5SDimitry Andric MFI.setStackSize(NumBytes); 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric emitSPAdjustment(MF, MBB, MBBI, -NumBytes, SAVErr, SAVEri); 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric unsigned regFP = RegInfo.getDwarfRegNum(SP::I6, true); 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric // Emit ".cfi_def_cfa_register 30". 1590b57cec5SDimitry Andric unsigned CFIIndex = 1600b57cec5SDimitry Andric MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, regFP)); 1610b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 1620b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric // Emit ".cfi_window_save". 1650b57cec5SDimitry Andric CFIIndex = MF.addFrameInst(MCCFIInstruction::createWindowSave(nullptr)); 1660b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 1670b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric unsigned regInRA = RegInfo.getDwarfRegNum(SP::I7, true); 1700b57cec5SDimitry Andric unsigned regOutRA = RegInfo.getDwarfRegNum(SP::O7, true); 1710b57cec5SDimitry Andric // Emit ".cfi_register 15, 31". 1720b57cec5SDimitry Andric CFIIndex = MF.addFrameInst( 1730b57cec5SDimitry Andric MCCFIInstruction::createRegister(nullptr, regOutRA, regInRA)); 1740b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 1750b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric if (NeedsStackRealignment) { 1780b57cec5SDimitry Andric int64_t Bias = Subtarget.getStackPointerBias(); 1790b57cec5SDimitry Andric unsigned regUnbiased; 1800b57cec5SDimitry Andric if (Bias) { 1810b57cec5SDimitry Andric // This clobbers G1 which we always know is available here. 1820b57cec5SDimitry Andric regUnbiased = SP::G1; 1830b57cec5SDimitry Andric // add %o6, BIAS, %g1 1840b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), regUnbiased) 1850b57cec5SDimitry Andric .addReg(SP::O6).addImm(Bias); 1860b57cec5SDimitry Andric } else 1870b57cec5SDimitry Andric regUnbiased = SP::O6; 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric // andn %regUnbiased, MaxAlign-1, %regUnbiased 190*5ffd83dbSDimitry Andric Align MaxAlign = MFI.getMaxAlign(); 1910b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::ANDNri), regUnbiased) 192*5ffd83dbSDimitry Andric .addReg(regUnbiased) 193*5ffd83dbSDimitry Andric .addImm(MaxAlign.value() - 1U); 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric if (Bias) { 1960b57cec5SDimitry Andric // add %g1, -BIAS, %o6 1970b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), SP::O6) 1980b57cec5SDimitry Andric .addReg(regUnbiased).addImm(-Bias); 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric MachineBasicBlock::iterator SparcFrameLowering:: 2040b57cec5SDimitry Andric eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 2050b57cec5SDimitry Andric MachineBasicBlock::iterator I) const { 2060b57cec5SDimitry Andric if (!hasReservedCallFrame(MF)) { 2070b57cec5SDimitry Andric MachineInstr &MI = *I; 2080b57cec5SDimitry Andric int Size = MI.getOperand(0).getImm(); 2090b57cec5SDimitry Andric if (MI.getOpcode() == SP::ADJCALLSTACKDOWN) 2100b57cec5SDimitry Andric Size = -Size; 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric if (Size) 2130b57cec5SDimitry Andric emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri); 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric return MBB.erase(I); 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric void SparcFrameLowering::emitEpilogue(MachineFunction &MF, 2200b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 2210b57cec5SDimitry Andric SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 2220b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 2230b57cec5SDimitry Andric const SparcInstrInfo &TII = 2240b57cec5SDimitry Andric *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo()); 2250b57cec5SDimitry Andric DebugLoc dl = MBBI->getDebugLoc(); 2260b57cec5SDimitry Andric assert(MBBI->getOpcode() == SP::RETL && 2270b57cec5SDimitry Andric "Can only put epilog before 'retl' instruction!"); 2280b57cec5SDimitry Andric if (!FuncInfo->isLeafProc()) { 2290b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0) 2300b57cec5SDimitry Andric .addReg(SP::G0); 2310b57cec5SDimitry Andric return; 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric int NumBytes = (int) MFI.getStackSize(); 2360b57cec5SDimitry Andric if (NumBytes == 0) 2370b57cec5SDimitry Andric return; 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri); 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric bool SparcFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { 2430b57cec5SDimitry Andric // Reserve call frame if there are no variable sized objects on the stack. 2440b57cec5SDimitry Andric return !MF.getFrameInfo().hasVarSizedObjects(); 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric // hasFP - Return true if the specified function should have a dedicated frame 2480b57cec5SDimitry Andric // pointer register. This is true if the function has variable sized allocas or 2490b57cec5SDimitry Andric // if frame pointer elimination is disabled. 2500b57cec5SDimitry Andric bool SparcFrameLowering::hasFP(const MachineFunction &MF) const { 2510b57cec5SDimitry Andric const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 2540b57cec5SDimitry Andric return MF.getTarget().Options.DisableFramePointerElim(MF) || 2550b57cec5SDimitry Andric RegInfo->needsStackRealignment(MF) || 2560b57cec5SDimitry Andric MFI.hasVarSizedObjects() || 2570b57cec5SDimitry Andric MFI.isFrameAddressTaken(); 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 260*5ffd83dbSDimitry Andric int SparcFrameLowering::getFrameIndexReference(const MachineFunction &MF, 261*5ffd83dbSDimitry Andric int FI, 262*5ffd83dbSDimitry Andric Register &FrameReg) const { 2630b57cec5SDimitry Andric const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>(); 2640b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 2650b57cec5SDimitry Andric const SparcRegisterInfo *RegInfo = Subtarget.getRegisterInfo(); 2660b57cec5SDimitry Andric const SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 2670b57cec5SDimitry Andric bool isFixed = MFI.isFixedObjectIndex(FI); 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric // Addressable stack objects are accessed using neg. offsets from 2700b57cec5SDimitry Andric // %fp, or positive offsets from %sp. 2710b57cec5SDimitry Andric bool UseFP; 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric // Sparc uses FP-based references in general, even when "hasFP" is 2740b57cec5SDimitry Andric // false. That function is rather a misnomer, because %fp is 2750b57cec5SDimitry Andric // actually always available, unless isLeafProc. 2760b57cec5SDimitry Andric if (FuncInfo->isLeafProc()) { 2770b57cec5SDimitry Andric // If there's a leaf proc, all offsets need to be %sp-based, 2780b57cec5SDimitry Andric // because we haven't caused %fp to actually point to our frame. 2790b57cec5SDimitry Andric UseFP = false; 2800b57cec5SDimitry Andric } else if (isFixed) { 2810b57cec5SDimitry Andric // Otherwise, argument access should always use %fp. 2820b57cec5SDimitry Andric UseFP = true; 2830b57cec5SDimitry Andric } else if (RegInfo->needsStackRealignment(MF)) { 2840b57cec5SDimitry Andric // If there is dynamic stack realignment, all local object 2850b57cec5SDimitry Andric // references need to be via %sp, to take account of the 2860b57cec5SDimitry Andric // re-alignment. 2870b57cec5SDimitry Andric UseFP = false; 2880b57cec5SDimitry Andric } else { 2890b57cec5SDimitry Andric // Finally, default to using %fp. 2900b57cec5SDimitry Andric UseFP = true; 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI) + 2940b57cec5SDimitry Andric Subtarget.getStackPointerBias(); 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric if (UseFP) { 2970b57cec5SDimitry Andric FrameReg = RegInfo->getFrameRegister(MF); 2980b57cec5SDimitry Andric return FrameOffset; 2990b57cec5SDimitry Andric } else { 3000b57cec5SDimitry Andric FrameReg = SP::O6; // %sp 3010b57cec5SDimitry Andric return FrameOffset + MF.getFrameInfo().getStackSize(); 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric } 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric static bool LLVM_ATTRIBUTE_UNUSED verifyLeafProcRegUse(MachineRegisterInfo *MRI) 3060b57cec5SDimitry Andric { 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) 3090b57cec5SDimitry Andric if (MRI->isPhysRegUsed(reg)) 3100b57cec5SDimitry Andric return false; 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric for (unsigned reg = SP::L0; reg <= SP::L7; ++reg) 3130b57cec5SDimitry Andric if (MRI->isPhysRegUsed(reg)) 3140b57cec5SDimitry Andric return false; 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric return true; 3170b57cec5SDimitry Andric } 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric bool SparcFrameLowering::isLeafProc(MachineFunction &MF) const 3200b57cec5SDimitry Andric { 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 3230b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric return !(MFI.hasCalls() // has calls 3260b57cec5SDimitry Andric || MRI.isPhysRegUsed(SP::L0) // Too many registers needed 3270b57cec5SDimitry Andric || MRI.isPhysRegUsed(SP::O6) // %sp is used 3280b57cec5SDimitry Andric || hasFP(MF)); // need %fp 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric void SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const { 3320b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 3330b57cec5SDimitry Andric // Remap %i[0-7] to %o[0-7]. 3340b57cec5SDimitry Andric for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) { 3350b57cec5SDimitry Andric if (!MRI.isPhysRegUsed(reg)) 3360b57cec5SDimitry Andric continue; 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric unsigned mapped_reg = reg - SP::I0 + SP::O0; 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric // Replace I register with O register. 3410b57cec5SDimitry Andric MRI.replaceRegWith(reg, mapped_reg); 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric // Also replace register pair super-registers. 3440b57cec5SDimitry Andric if ((reg - SP::I0) % 2 == 0) { 3450b57cec5SDimitry Andric unsigned preg = (reg - SP::I0) / 2 + SP::I0_I1; 3460b57cec5SDimitry Andric unsigned mapped_preg = preg - SP::I0_I1 + SP::O0_O1; 3470b57cec5SDimitry Andric MRI.replaceRegWith(preg, mapped_preg); 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric // Rewrite MBB's Live-ins. 3520b57cec5SDimitry Andric for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); 3530b57cec5SDimitry Andric MBB != E; ++MBB) { 3540b57cec5SDimitry Andric for (unsigned reg = SP::I0_I1; reg <= SP::I6_I7; ++reg) { 3550b57cec5SDimitry Andric if (!MBB->isLiveIn(reg)) 3560b57cec5SDimitry Andric continue; 3570b57cec5SDimitry Andric MBB->removeLiveIn(reg); 3580b57cec5SDimitry Andric MBB->addLiveIn(reg - SP::I0_I1 + SP::O0_O1); 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) { 3610b57cec5SDimitry Andric if (!MBB->isLiveIn(reg)) 3620b57cec5SDimitry Andric continue; 3630b57cec5SDimitry Andric MBB->removeLiveIn(reg); 3640b57cec5SDimitry Andric MBB->addLiveIn(reg - SP::I0 + SP::O0); 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric assert(verifyLeafProcRegUse(&MRI)); 3690b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 3700b57cec5SDimitry Andric MF.verify(0, "After LeafProc Remapping"); 3710b57cec5SDimitry Andric #endif 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric void SparcFrameLowering::determineCalleeSaves(MachineFunction &MF, 3750b57cec5SDimitry Andric BitVector &SavedRegs, 3760b57cec5SDimitry Andric RegScavenger *RS) const { 3770b57cec5SDimitry Andric TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 3780b57cec5SDimitry Andric if (!DisableLeafProc && isLeafProc(MF)) { 3790b57cec5SDimitry Andric SparcMachineFunctionInfo *MFI = MF.getInfo<SparcMachineFunctionInfo>(); 3800b57cec5SDimitry Andric MFI->setLeafProc(true); 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric remapRegsForLeafProc(MF); 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric } 386