//===-- VEFrameLowering.cpp - VE Frame Information ------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains the VE implementation of TargetFrameLowering class. // //===----------------------------------------------------------------------===// #include "VEFrameLowering.h" #include "VEInstrInfo.h" #include "VESubtarget.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/MathExtras.h" using namespace llvm; VEFrameLowering::VEFrameLowering(const VESubtarget &ST) : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(16), 0, Align(16)) {} void VEFrameLowering::emitPrologueInsns(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, int NumBytes, bool RequireFPUpdate) const { DebugLoc dl; const VEInstrInfo &TII = *static_cast(MF.getSubtarget().getInstrInfo()); // Insert following codes here as prologue // // st %fp, 0(,%sp) // st %lr, 8(,%sp) // st %got, 24(,%sp) // st %plt, 32(,%sp) // or %fp, 0, %sp BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) .addReg(VE::SX11) .addImm(0) .addReg(VE::SX9); BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) .addReg(VE::SX11) .addImm(8) .addReg(VE::SX10); BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) .addReg(VE::SX11) .addImm(24) .addReg(VE::SX15); BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) .addReg(VE::SX11) .addImm(32) .addReg(VE::SX16); BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX9) .addReg(VE::SX11) .addImm(0); } void VEFrameLowering::emitEpilogueInsns(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, int NumBytes, bool RequireFPUpdate) const { DebugLoc dl; const VEInstrInfo &TII = *static_cast(MF.getSubtarget().getInstrInfo()); // Insert following codes here as epilogue // // or %sp, 0, %fp // ld %got, 32(,%sp) // ld %plt, 24(,%sp) // ld %lr, 8(,%sp) // ld %fp, 0(,%sp) BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX11) .addReg(VE::SX9) .addImm(0); BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX16) .addReg(VE::SX11) .addImm(32); BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX15) .addReg(VE::SX11) .addImm(24); BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX10) .addReg(VE::SX11) .addImm(8); BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX9) .addReg(VE::SX11) .addImm(0); } void VEFrameLowering::emitSPAdjustment(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, int NumBytes) const { DebugLoc dl; const VEInstrInfo &TII = *static_cast(MF.getSubtarget().getInstrInfo()); if (NumBytes >= -64 && NumBytes < 63) { BuildMI(MBB, MBBI, dl, TII.get(VE::ADXri), VE::SX11) .addReg(VE::SX11) .addImm(NumBytes); return; } // Emit following codes. This clobbers SX13 which we always know is // available here. // lea %s13,%lo(NumBytes) // and %s13,%s13,(32)0 // lea.sl %sp,%hi(NumBytes)(%sp, %s13) BuildMI(MBB, MBBI, dl, TII.get(VE::LEAzzi), VE::SX13) .addImm(LO32(NumBytes)); BuildMI(MBB, MBBI, dl, TII.get(VE::ANDrm0), VE::SX13) .addReg(VE::SX13) .addImm(32); BuildMI(MBB, MBBI, dl, TII.get(VE::LEASLrri), VE::SX11) .addReg(VE::SX11) .addReg(VE::SX13) .addImm(HI32(NumBytes)); } void VEFrameLowering::emitSPExtend(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, int NumBytes) const { DebugLoc dl; const VEInstrInfo &TII = *static_cast(MF.getSubtarget().getInstrInfo()); // Emit following codes. It is not possible to insert multiple // BasicBlocks in PEI pass, so we emit two pseudo instructions here. // // EXTEND_STACK // pseudo instrcution // EXTEND_STACK_GUARD // pseudo instrcution // // EXTEND_STACK pseudo will be converted by ExpandPostRA pass into // following instructions with multiple basic blocks later. // // thisBB: // brge.l.t %sp, %sl, sinkBB // syscallBB: // ld %s61, 0x18(, %tp) // load param area // or %s62, 0, %s0 // spill the value of %s0 // lea %s63, 0x13b // syscall # of grow // shm.l %s63, 0x0(%s61) // store syscall # at addr:0 // shm.l %sl, 0x8(%s61) // store old limit at addr:8 // shm.l %sp, 0x10(%s61) // store new limit at addr:16 // monc // call monitor // or %s0, 0, %s62 // restore the value of %s0 // sinkBB: // // EXTEND_STACK_GUARD pseudo will be simply eliminated by ExpandPostRA // pass. This pseudo is required to be at the next of EXTEND_STACK // pseudo in order to protect iteration loop in ExpandPostRA. BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK)); BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK_GUARD)); } void VEFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); MachineFrameInfo &MFI = MF.getFrameInfo(); const VESubtarget &Subtarget = MF.getSubtarget(); const VEInstrInfo &TII = *static_cast(Subtarget.getInstrInfo()); const VERegisterInfo &RegInfo = *static_cast(Subtarget.getRegisterInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); // Debug location must be unknown since the first debug location is used // to determine the end of the prologue. DebugLoc dl; bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF); // FIXME: unfortunately, returning false from canRealignStack // actually just causes needsStackRealignment to return false, // rather than reporting an error, as would be sensible. This is // poor, but fixing that bogosity is going to be a large project. // For now, just see if it's lied, and report an error here. if (!NeedsStackRealignment && MFI.getMaxAlignment() > getStackAlignment()) report_fatal_error("Function \"" + Twine(MF.getName()) + "\" required " "stack re-alignment, but LLVM couldn't handle it " "(probably because it has a dynamic alloca)."); // Get the number of bytes to allocate from the FrameInfo int NumBytes = (int)MFI.getStackSize(); // The VE ABI requires a reserved 176-byte area in the user's stack, starting // at %sp + 16. This is for the callee Register Save Area (RSA). // // We therefore need to add that offset to the total stack size // after all the stack objects are placed by // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack // needs to be aligned *after* the extra size is added, we need to disable // calculateFrameObjectOffsets's built-in stack alignment, by having // targetHandlesStackFrameRounding return true. // Add the extra call frame stack size, if needed. (This is the same // code as in PrologEpilogInserter, but also gets disabled by // targetHandlesStackFrameRounding) if (MFI.adjustsStack() && hasReservedCallFrame(MF)) NumBytes += MFI.getMaxCallFrameSize(); // Adds the VE subtarget-specific spill area to the stack // size. Also ensures target-required alignment. NumBytes = Subtarget.getAdjustedFrameSize(NumBytes); // Finally, ensure that the size is sufficiently aligned for the // data on the stack. if (MFI.getMaxAlignment() > 0) { NumBytes = alignTo(NumBytes, MFI.getMaxAlignment()); } // Update stack size with corrected value. MFI.setStackSize(NumBytes); // Emit Prologue instructions to save %lr emitPrologueInsns(MF, MBB, MBBI, NumBytes, true); // Emit stack adjust instructions emitSPAdjustment(MF, MBB, MBBI, -NumBytes); // Emit stack extend instructions emitSPExtend(MF, MBB, MBBI, -NumBytes); unsigned regFP = RegInfo.getDwarfRegNum(VE::SX9, true); // Emit ".cfi_def_cfa_register 30". unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, regFP)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); // Emit ".cfi_window_save". CFIIndex = MF.addFrameInst(MCCFIInstruction::createWindowSave(nullptr)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } MachineBasicBlock::iterator VEFrameLowering::eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { if (!hasReservedCallFrame(MF)) { MachineInstr &MI = *I; int Size = MI.getOperand(0).getImm(); if (MI.getOpcode() == VE::ADJCALLSTACKDOWN) Size = -Size; if (Size) emitSPAdjustment(MF, MBB, I, Size); } return MBB.erase(I); } void VEFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); DebugLoc dl = MBBI->getDebugLoc(); MachineFrameInfo &MFI = MF.getFrameInfo(); int NumBytes = (int)MFI.getStackSize(); // Emit Epilogue instructions to restore %lr emitEpilogueInsns(MF, MBB, MBBI, NumBytes, true); } bool VEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { // Reserve call frame if there are no variable sized objects on the stack. return !MF.getFrameInfo().hasVarSizedObjects(); } // hasFP - Return true if the specified function should have a dedicated frame // pointer register. This is true if the function has variable sized allocas or // if frame pointer elimination is disabled. bool VEFrameLowering::hasFP(const MachineFunction &MF) const { const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); const MachineFrameInfo &MFI = MF.getFrameInfo(); return MF.getTarget().Options.DisableFramePointerElim(MF) || RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken(); } int VEFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const { // Addressable stack objects are accessed using neg. offsets from // %fp, or positive offsets from %sp. int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI); FrameReg = VE::SX11; // %sp return FrameOffset + MF.getFrameInfo().getStackSize(); } bool VEFrameLowering::isLeafProc(MachineFunction &MF) const { MachineRegisterInfo &MRI = MF.getRegInfo(); MachineFrameInfo &MFI = MF.getFrameInfo(); return !MFI.hasCalls() // No calls && !MRI.isPhysRegUsed(VE::SX18) // Registers within limits // (s18 is first CSR) && !MRI.isPhysRegUsed(VE::SX11) // %sp un-used && !hasFP(MF); // Don't need %fp } void VEFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const { TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); assert(isLeafProc(MF) && "TODO implement for non-leaf procs"); }