Path: blob/main/contrib/llvm-project/llvm/lib/Target/Sparc/SparcFrameLowering.cpp
35266 views
//===-- SparcFrameLowering.cpp - Sparc Frame Information ------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains the Sparc implementation of TargetFrameLowering class.9//10//===----------------------------------------------------------------------===//1112#include "SparcFrameLowering.h"13#include "SparcInstrInfo.h"14#include "SparcMachineFunctionInfo.h"15#include "SparcSubtarget.h"16#include "llvm/CodeGen/MachineFrameInfo.h"17#include "llvm/CodeGen/MachineFunction.h"18#include "llvm/CodeGen/MachineInstrBuilder.h"19#include "llvm/CodeGen/MachineModuleInfo.h"20#include "llvm/CodeGen/MachineRegisterInfo.h"21#include "llvm/IR/DataLayout.h"22#include "llvm/IR/Function.h"23#include "llvm/Support/CommandLine.h"24#include "llvm/Target/TargetOptions.h"2526using namespace llvm;2728static cl::opt<bool>29DisableLeafProc("disable-sparc-leaf-proc",30cl::init(false),31cl::desc("Disable Sparc leaf procedure optimization."),32cl::Hidden);3334SparcFrameLowering::SparcFrameLowering(const SparcSubtarget &ST)35: TargetFrameLowering(TargetFrameLowering::StackGrowsDown,36ST.is64Bit() ? Align(16) : Align(8), 0,37ST.is64Bit() ? Align(16) : Align(8)) {}3839void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF,40MachineBasicBlock &MBB,41MachineBasicBlock::iterator MBBI,42int NumBytes,43unsigned ADDrr,44unsigned ADDri) const {4546DebugLoc dl;47const SparcInstrInfo &TII =48*static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());4950if (NumBytes >= -4096 && NumBytes < 4096) {51BuildMI(MBB, MBBI, dl, TII.get(ADDri), SP::O6)52.addReg(SP::O6).addImm(NumBytes);53return;54}5556// Emit this the hard way. This clobbers G1 which we always know is57// available here.58if (NumBytes >= 0) {59// Emit nonnegative numbers with sethi + or.60// sethi %hi(NumBytes), %g161// or %g1, %lo(NumBytes), %g162// add %sp, %g1, %sp63BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)64.addImm(HI22(NumBytes));65BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)66.addReg(SP::G1).addImm(LO10(NumBytes));67BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)68.addReg(SP::O6).addReg(SP::G1);69return ;70}7172// Emit negative numbers with sethi + xor.73// sethi %hix(NumBytes), %g174// xor %g1, %lox(NumBytes), %g175// add %sp, %g1, %sp76BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)77.addImm(HIX22(NumBytes));78BuildMI(MBB, MBBI, dl, TII.get(SP::XORri), SP::G1)79.addReg(SP::G1).addImm(LOX10(NumBytes));80BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)81.addReg(SP::O6).addReg(SP::G1);82}8384void SparcFrameLowering::emitPrologue(MachineFunction &MF,85MachineBasicBlock &MBB) const {86SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();8788assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");89MachineFrameInfo &MFI = MF.getFrameInfo();90const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();91const SparcInstrInfo &TII =92*static_cast<const SparcInstrInfo *>(Subtarget.getInstrInfo());93const SparcRegisterInfo &RegInfo =94*static_cast<const SparcRegisterInfo *>(Subtarget.getRegisterInfo());95MachineBasicBlock::iterator MBBI = MBB.begin();96// Debug location must be unknown since the first debug location is used97// to determine the end of the prologue.98DebugLoc dl;99bool NeedsStackRealignment = RegInfo.shouldRealignStack(MF);100101if (NeedsStackRealignment && !RegInfo.canRealignStack(MF))102report_fatal_error("Function \"" + Twine(MF.getName()) + "\" required "103"stack re-alignment, but LLVM couldn't handle it "104"(probably because it has a dynamic alloca).");105106// Get the number of bytes to allocate from the FrameInfo107int NumBytes = (int) MFI.getStackSize();108109unsigned SAVEri = SP::SAVEri;110unsigned SAVErr = SP::SAVErr;111if (FuncInfo->isLeafProc()) {112if (NumBytes == 0)113return;114SAVEri = SP::ADDri;115SAVErr = SP::ADDrr;116}117118// The SPARC ABI is a bit odd in that it requires a reserved 92-byte119// (128 in v9) area in the user's stack, starting at %sp. Thus, the120// first part of the stack that can actually be used is located at121// %sp + 92.122//123// We therefore need to add that offset to the total stack size124// after all the stack objects are placed by125// PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack needs to be126// aligned *after* the extra size is added, we need to disable127// calculateFrameObjectOffsets's built-in stack alignment, by having128// targetHandlesStackFrameRounding return true.129130131// Add the extra call frame stack size, if needed. (This is the same132// code as in PrologEpilogInserter, but also gets disabled by133// targetHandlesStackFrameRounding)134if (MFI.adjustsStack() && hasReservedCallFrame(MF))135NumBytes += MFI.getMaxCallFrameSize();136137// Adds the SPARC subtarget-specific spill area to the stack138// size. Also ensures target-required alignment.139NumBytes = Subtarget.getAdjustedFrameSize(NumBytes);140141// Finally, ensure that the size is sufficiently aligned for the142// data on the stack.143NumBytes = alignTo(NumBytes, MFI.getMaxAlign());144145// Update stack size with corrected value.146MFI.setStackSize(NumBytes);147148emitSPAdjustment(MF, MBB, MBBI, -NumBytes, SAVErr, SAVEri);149150unsigned regFP = RegInfo.getDwarfRegNum(SP::I6, true);151152// Emit ".cfi_def_cfa_register 30".153unsigned CFIIndex =154MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, regFP));155BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))156.addCFIIndex(CFIIndex);157158// Emit ".cfi_window_save".159CFIIndex = MF.addFrameInst(MCCFIInstruction::createWindowSave(nullptr));160BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))161.addCFIIndex(CFIIndex);162163unsigned regInRA = RegInfo.getDwarfRegNum(SP::I7, true);164unsigned regOutRA = RegInfo.getDwarfRegNum(SP::O7, true);165// Emit ".cfi_register 15, 31".166CFIIndex = MF.addFrameInst(167MCCFIInstruction::createRegister(nullptr, regOutRA, regInRA));168BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))169.addCFIIndex(CFIIndex);170171if (NeedsStackRealignment) {172int64_t Bias = Subtarget.getStackPointerBias();173unsigned regUnbiased;174if (Bias) {175// This clobbers G1 which we always know is available here.176regUnbiased = SP::G1;177// add %o6, BIAS, %g1178BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), regUnbiased)179.addReg(SP::O6).addImm(Bias);180} else181regUnbiased = SP::O6;182183// andn %regUnbiased, MaxAlign-1, %regUnbiased184Align MaxAlign = MFI.getMaxAlign();185BuildMI(MBB, MBBI, dl, TII.get(SP::ANDNri), regUnbiased)186.addReg(regUnbiased)187.addImm(MaxAlign.value() - 1U);188189if (Bias) {190// add %g1, -BIAS, %o6191BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), SP::O6)192.addReg(regUnbiased).addImm(-Bias);193}194}195}196197MachineBasicBlock::iterator SparcFrameLowering::198eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,199MachineBasicBlock::iterator I) const {200if (!hasReservedCallFrame(MF)) {201MachineInstr &MI = *I;202int Size = MI.getOperand(0).getImm();203if (MI.getOpcode() == SP::ADJCALLSTACKDOWN)204Size = -Size;205206if (Size)207emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri);208}209return MBB.erase(I);210}211212213void SparcFrameLowering::emitEpilogue(MachineFunction &MF,214MachineBasicBlock &MBB) const {215SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();216MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();217const SparcInstrInfo &TII =218*static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());219DebugLoc dl = MBBI->getDebugLoc();220assert((MBBI->getOpcode() == SP::RETL || MBBI->getOpcode() == SP::TAIL_CALL ||221MBBI->getOpcode() == SP::TAIL_CALLri) &&222"Can only put epilog before 'retl' or 'tail_call' instruction!");223if (!FuncInfo->isLeafProc()) {224BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0)225.addReg(SP::G0);226return;227}228MachineFrameInfo &MFI = MF.getFrameInfo();229230int NumBytes = (int) MFI.getStackSize();231if (NumBytes != 0)232emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri);233234// Preserve return address in %o7235if (MBBI->getOpcode() == SP::TAIL_CALL) {236MBB.addLiveIn(SP::O7);237BuildMI(MBB, MBBI, dl, TII.get(SP::ORrr), SP::G1)238.addReg(SP::G0)239.addReg(SP::O7);240BuildMI(MBB, MBBI, dl, TII.get(SP::ORrr), SP::O7)241.addReg(SP::G0)242.addReg(SP::G1);243}244}245246bool SparcFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {247// Reserve call frame if there are no variable sized objects on the stack.248return !MF.getFrameInfo().hasVarSizedObjects();249}250251// hasFP - Return true if the specified function should have a dedicated frame252// pointer register. This is true if the function has variable sized allocas or253// if frame pointer elimination is disabled.254bool SparcFrameLowering::hasFP(const MachineFunction &MF) const {255const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();256257const MachineFrameInfo &MFI = MF.getFrameInfo();258return MF.getTarget().Options.DisableFramePointerElim(MF) ||259RegInfo->hasStackRealignment(MF) || MFI.hasVarSizedObjects() ||260MFI.isFrameAddressTaken();261}262263StackOffset264SparcFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,265Register &FrameReg) const {266const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();267const MachineFrameInfo &MFI = MF.getFrameInfo();268const SparcRegisterInfo *RegInfo = Subtarget.getRegisterInfo();269const SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();270bool isFixed = MFI.isFixedObjectIndex(FI);271272// Addressable stack objects are accessed using neg. offsets from273// %fp, or positive offsets from %sp.274bool UseFP;275276// Sparc uses FP-based references in general, even when "hasFP" is277// false. That function is rather a misnomer, because %fp is278// actually always available, unless isLeafProc.279if (FuncInfo->isLeafProc()) {280// If there's a leaf proc, all offsets need to be %sp-based,281// because we haven't caused %fp to actually point to our frame.282UseFP = false;283} else if (isFixed) {284// Otherwise, argument access should always use %fp.285UseFP = true;286} else if (RegInfo->hasStackRealignment(MF)) {287// If there is dynamic stack realignment, all local object288// references need to be via %sp, to take account of the289// re-alignment.290UseFP = false;291} else {292// Finally, default to using %fp.293UseFP = true;294}295296int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI) +297Subtarget.getStackPointerBias();298299if (UseFP) {300FrameReg = RegInfo->getFrameRegister(MF);301return StackOffset::getFixed(FrameOffset);302} else {303FrameReg = SP::O6; // %sp304return StackOffset::getFixed(FrameOffset + MF.getFrameInfo().getStackSize());305}306}307308static bool LLVM_ATTRIBUTE_UNUSED verifyLeafProcRegUse(MachineRegisterInfo *MRI)309{310311for (unsigned reg = SP::I0; reg <= SP::I7; ++reg)312if (MRI->isPhysRegUsed(reg))313return false;314315for (unsigned reg = SP::L0; reg <= SP::L7; ++reg)316if (MRI->isPhysRegUsed(reg))317return false;318319return true;320}321322bool SparcFrameLowering::isLeafProc(MachineFunction &MF) const323{324325MachineRegisterInfo &MRI = MF.getRegInfo();326MachineFrameInfo &MFI = MF.getFrameInfo();327328return !(MFI.hasCalls() // has calls329|| MRI.isPhysRegUsed(SP::L0) // Too many registers needed330|| MRI.isPhysRegUsed(SP::O6) // %sp is used331|| hasFP(MF) // need %fp332|| MF.hasInlineAsm()); // has inline assembly333}334335void SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const {336MachineRegisterInfo &MRI = MF.getRegInfo();337// Remap %i[0-7] to %o[0-7].338for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {339if (!MRI.isPhysRegUsed(reg))340continue;341342unsigned mapped_reg = reg - SP::I0 + SP::O0;343344// Replace I register with O register.345MRI.replaceRegWith(reg, mapped_reg);346347// Also replace register pair super-registers.348if ((reg - SP::I0) % 2 == 0) {349unsigned preg = (reg - SP::I0) / 2 + SP::I0_I1;350unsigned mapped_preg = preg - SP::I0_I1 + SP::O0_O1;351MRI.replaceRegWith(preg, mapped_preg);352}353}354355// Rewrite MBB's Live-ins.356for (MachineBasicBlock &MBB : MF) {357for (unsigned reg = SP::I0_I1; reg <= SP::I6_I7; ++reg) {358if (!MBB.isLiveIn(reg))359continue;360MBB.removeLiveIn(reg);361MBB.addLiveIn(reg - SP::I0_I1 + SP::O0_O1);362}363for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {364if (!MBB.isLiveIn(reg))365continue;366MBB.removeLiveIn(reg);367MBB.addLiveIn(reg - SP::I0 + SP::O0);368}369}370371assert(verifyLeafProcRegUse(&MRI));372#ifdef EXPENSIVE_CHECKS373MF.verify(0, "After LeafProc Remapping");374#endif375}376377void SparcFrameLowering::determineCalleeSaves(MachineFunction &MF,378BitVector &SavedRegs,379RegScavenger *RS) const {380TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);381if (!DisableLeafProc && isLeafProc(MF)) {382SparcMachineFunctionInfo *MFI = MF.getInfo<SparcMachineFunctionInfo>();383MFI->setLeafProc(true);384385remapRegsForLeafProc(MF);386}387388}389390391