329 lines · cpp
1//===-- SparcFrameLowering.cpp - Sparc Frame Information ------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the Sparc implementation of TargetFrameLowering class.10//11//===----------------------------------------------------------------------===//12 13#include "SparcFrameLowering.h"14#include "SparcInstrInfo.h"15#include "SparcMachineFunctionInfo.h"16#include "SparcSubtarget.h"17#include "llvm/CodeGen/CFIInstBuilder.h"18#include "llvm/CodeGen/MachineFrameInfo.h"19#include "llvm/CodeGen/MachineFunction.h"20#include "llvm/CodeGen/MachineInstrBuilder.h"21#include "llvm/CodeGen/MachineModuleInfo.h"22#include "llvm/CodeGen/MachineRegisterInfo.h"23#include "llvm/Support/CommandLine.h"24#include "llvm/Target/TargetOptions.h"25 26using namespace llvm;27 28static cl::opt<bool>29DisableLeafProc("disable-sparc-leaf-proc",30 cl::init(false),31 cl::desc("Disable Sparc leaf procedure optimization."),32 cl::Hidden);33 34SparcFrameLowering::SparcFrameLowering(const SparcSubtarget &ST)35 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown,36 ST.is64Bit() ? Align(16) : Align(8), 0,37 ST.is64Bit() ? Align(16) : Align(8),38 /*StackRealignable=*/false) {}39 40void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF,41 MachineBasicBlock &MBB,42 MachineBasicBlock::iterator MBBI,43 int NumBytes,44 unsigned ADDrr,45 unsigned ADDri) const {46 47 DebugLoc dl;48 const SparcInstrInfo &TII =49 *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());50 51 if (NumBytes >= -4096 && NumBytes < 4096) {52 BuildMI(MBB, MBBI, dl, TII.get(ADDri), SP::O6)53 .addReg(SP::O6).addImm(NumBytes);54 return;55 }56 57 // Emit this the hard way. This clobbers G1 which we always know is58 // available here.59 if (NumBytes >= 0) {60 // Emit nonnegative numbers with sethi + or.61 // sethi %hi(NumBytes), %g162 // or %g1, %lo(NumBytes), %g163 // add %sp, %g1, %sp64 BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)65 .addImm(HI22(NumBytes));66 BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)67 .addReg(SP::G1).addImm(LO10(NumBytes));68 BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)69 .addReg(SP::O6).addReg(SP::G1);70 return ;71 }72 73 // Emit negative numbers with sethi + xor.74 // sethi %hix(NumBytes), %g175 // xor %g1, %lox(NumBytes), %g176 // add %sp, %g1, %sp77 BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)78 .addImm(HIX22(NumBytes));79 BuildMI(MBB, MBBI, dl, TII.get(SP::XORri), SP::G1)80 .addReg(SP::G1).addImm(LOX10(NumBytes));81 BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)82 .addReg(SP::O6).addReg(SP::G1);83}84 85void SparcFrameLowering::emitPrologue(MachineFunction &MF,86 MachineBasicBlock &MBB) const {87 SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();88 89 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");90 MachineFrameInfo &MFI = MF.getFrameInfo();91 const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();92 MachineBasicBlock::iterator MBBI = MBB.begin();93 94 // Get the number of bytes to allocate from the FrameInfo95 int NumBytes = (int) MFI.getStackSize();96 97 unsigned SAVEri = SP::SAVEri;98 unsigned SAVErr = SP::SAVErr;99 if (FuncInfo->isLeafProc()) {100 if (NumBytes == 0)101 return;102 SAVEri = SP::ADDri;103 SAVErr = SP::ADDrr;104 }105 106 // The SPARC ABI is a bit odd in that it requires a reserved 92-byte107 // (128 in v9) area in the user's stack, starting at %sp. Thus, the108 // first part of the stack that can actually be used is located at109 // %sp + 92.110 //111 // We therefore need to add that offset to the total stack size112 // after all the stack objects are placed by113 // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack needs to be114 // aligned *after* the extra size is added, we need to disable115 // calculateFrameObjectOffsets's built-in stack alignment, by having116 // targetHandlesStackFrameRounding return true.117 118 119 // Add the extra call frame stack size, if needed. (This is the same120 // code as in PrologEpilogInserter, but also gets disabled by121 // targetHandlesStackFrameRounding)122 if (MFI.adjustsStack() && hasReservedCallFrame(MF))123 NumBytes += MFI.getMaxCallFrameSize();124 125 // Adds the SPARC subtarget-specific spill area to the stack126 // size. Also ensures target-required alignment.127 NumBytes = Subtarget.getAdjustedFrameSize(NumBytes);128 129 // Finally, ensure that the size is sufficiently aligned for the130 // data on the stack.131 NumBytes = alignTo(NumBytes, MFI.getMaxAlign());132 133 // Update stack size with corrected value.134 MFI.setStackSize(NumBytes);135 136 emitSPAdjustment(MF, MBB, MBBI, -NumBytes, SAVErr, SAVEri);137 138 if (MF.needsFrameMoves()) {139 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::NoFlags);140 CFIBuilder.buildDefCFARegister(SP::I6);141 CFIBuilder.buildWindowSave();142 CFIBuilder.buildRegister(SP::O7, SP::I7);143 }144}145 146MachineBasicBlock::iterator SparcFrameLowering::147eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,148 MachineBasicBlock::iterator I) const {149 if (!hasReservedCallFrame(MF)) {150 MachineInstr &MI = *I;151 int Size = MI.getOperand(0).getImm();152 if (MI.getOpcode() == SP::ADJCALLSTACKDOWN)153 Size = -Size;154 155 if (Size)156 emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri);157 }158 return MBB.erase(I);159}160 161 162void SparcFrameLowering::emitEpilogue(MachineFunction &MF,163 MachineBasicBlock &MBB) const {164 SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();165 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();166 const SparcInstrInfo &TII =167 *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());168 DebugLoc dl = MBBI->getDebugLoc();169 assert((MBBI->getOpcode() == SP::RETL || MBBI->getOpcode() == SP::TAIL_CALL ||170 MBBI->getOpcode() == SP::TAIL_CALLri) &&171 "Can only put epilog before 'retl' or 'tail_call' instruction!");172 if (!FuncInfo->isLeafProc()) {173 BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0)174 .addReg(SP::G0);175 return;176 }177 MachineFrameInfo &MFI = MF.getFrameInfo();178 179 int NumBytes = (int) MFI.getStackSize();180 if (NumBytes != 0)181 emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri);182 183 // Preserve return address in %o7184 if (MBBI->getOpcode() == SP::TAIL_CALL) {185 MBB.addLiveIn(SP::O7);186 BuildMI(MBB, MBBI, dl, TII.get(SP::ORrr), SP::G1)187 .addReg(SP::G0)188 .addReg(SP::O7);189 BuildMI(MBB, MBBI, dl, TII.get(SP::ORrr), SP::O7)190 .addReg(SP::G0)191 .addReg(SP::G1);192 }193}194 195bool SparcFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {196 // Reserve call frame if there are no variable sized objects on the stack.197 return !MF.getFrameInfo().hasVarSizedObjects();198}199 200// hasFPImpl - Return true if the specified function should have a dedicated201// frame pointer register. This is true if the function has variable sized202// allocas or if frame pointer elimination is disabled.203bool SparcFrameLowering::hasFPImpl(const MachineFunction &MF) const {204 const MachineFrameInfo &MFI = MF.getFrameInfo();205 return MF.getTarget().Options.DisableFramePointerElim(MF) ||206 MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken();207}208 209StackOffset210SparcFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,211 Register &FrameReg) const {212 const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();213 const MachineFrameInfo &MFI = MF.getFrameInfo();214 const SparcRegisterInfo *RegInfo = Subtarget.getRegisterInfo();215 const SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();216 bool isFixed = MFI.isFixedObjectIndex(FI);217 218 // Addressable stack objects are accessed using neg. offsets from219 // %fp, or positive offsets from %sp.220 bool UseFP;221 222 // Sparc uses FP-based references in general, even when "hasFP" is223 // false. That function is rather a misnomer, because %fp is224 // actually always available, unless isLeafProc.225 if (FuncInfo->isLeafProc()) {226 // If there's a leaf proc, all offsets need to be %sp-based,227 // because we haven't caused %fp to actually point to our frame.228 UseFP = false;229 } else if (isFixed) {230 // Otherwise, argument access should always use %fp.231 UseFP = true;232 } else {233 // Finally, default to using %fp.234 UseFP = true;235 }236 237 int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI) +238 Subtarget.getStackPointerBias();239 240 if (UseFP) {241 FrameReg = RegInfo->getFrameRegister(MF);242 return StackOffset::getFixed(FrameOffset);243 } else {244 FrameReg = SP::O6; // %sp245 return StackOffset::getFixed(FrameOffset + MF.getFrameInfo().getStackSize());246 }247}248 249[[maybe_unused]] static bool verifyLeafProcRegUse(MachineRegisterInfo *MRI) {250 251 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg)252 if (MRI->isPhysRegUsed(reg))253 return false;254 255 for (unsigned reg = SP::L0; reg <= SP::L7; ++reg)256 if (MRI->isPhysRegUsed(reg))257 return false;258 259 return true;260}261 262bool SparcFrameLowering::isLeafProc(MachineFunction &MF) const263{264 265 MachineRegisterInfo &MRI = MF.getRegInfo();266 MachineFrameInfo &MFI = MF.getFrameInfo();267 268 return !(MFI.hasCalls() // has calls269 || MRI.isPhysRegUsed(SP::L0) // Too many registers needed270 || MRI.isPhysRegUsed(SP::O6) // %sp is used271 || hasFP(MF) // need %fp272 || MF.hasInlineAsm()); // has inline assembly273}274 275void SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const {276 MachineRegisterInfo &MRI = MF.getRegInfo();277 // Remap %i[0-7] to %o[0-7].278 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {279 if (!MRI.isPhysRegUsed(reg))280 continue;281 282 unsigned mapped_reg = reg - SP::I0 + SP::O0;283 284 // Replace I register with O register.285 MRI.replaceRegWith(reg, mapped_reg);286 287 // Also replace register pair super-registers.288 if ((reg - SP::I0) % 2 == 0) {289 unsigned preg = (reg - SP::I0) / 2 + SP::I0_I1;290 unsigned mapped_preg = preg - SP::I0_I1 + SP::O0_O1;291 MRI.replaceRegWith(preg, mapped_preg);292 }293 }294 295 // Rewrite MBB's Live-ins.296 for (MachineBasicBlock &MBB : MF) {297 for (unsigned reg = SP::I0_I1; reg <= SP::I6_I7; ++reg) {298 if (!MBB.isLiveIn(reg))299 continue;300 MBB.removeLiveIn(reg);301 MBB.addLiveIn(reg - SP::I0_I1 + SP::O0_O1);302 }303 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {304 if (!MBB.isLiveIn(reg))305 continue;306 MBB.removeLiveIn(reg);307 MBB.addLiveIn(reg - SP::I0 + SP::O0);308 }309 }310 311 assert(verifyLeafProcRegUse(&MRI));312#ifdef EXPENSIVE_CHECKS313 MF.verify(0, "After LeafProc Remapping");314#endif315}316 317void SparcFrameLowering::determineCalleeSaves(MachineFunction &MF,318 BitVector &SavedRegs,319 RegScavenger *RS) const {320 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);321 if (!DisableLeafProc && isLeafProc(MF)) {322 SparcMachineFunctionInfo *MFI = MF.getInfo<SparcMachineFunctionInfo>();323 MFI->setLeafProc(true);324 325 remapRegsForLeafProc(MF);326 }327 328}329