1356843Sdim//===-- VEFrameLowering.cpp - VE Frame Information ------------------------===// 2356843Sdim// 3356843Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4356843Sdim// See https://llvm.org/LICENSE.txt for license information. 5356843Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6356843Sdim// 7356843Sdim//===----------------------------------------------------------------------===// 8356843Sdim// 9356843Sdim// This file contains the VE implementation of TargetFrameLowering class. 10356843Sdim// 11356843Sdim//===----------------------------------------------------------------------===// 12356843Sdim 13356843Sdim#include "VEFrameLowering.h" 14356843Sdim#include "VEInstrInfo.h" 15356843Sdim#include "VESubtarget.h" 16356843Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 17356843Sdim#include "llvm/CodeGen/MachineFunction.h" 18356843Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 19356843Sdim#include "llvm/CodeGen/MachineModuleInfo.h" 20356843Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 21356843Sdim#include "llvm/CodeGen/RegisterScavenging.h" 22356843Sdim#include "llvm/IR/DataLayout.h" 23356843Sdim#include "llvm/IR/Function.h" 24356843Sdim#include "llvm/Support/CommandLine.h" 25356843Sdim#include "llvm/Target/TargetOptions.h" 26356843Sdim#include "llvm/Support/MathExtras.h" 27356843Sdim 28356843Sdimusing namespace llvm; 29356843Sdim 30356843SdimVEFrameLowering::VEFrameLowering(const VESubtarget &ST) 31356843Sdim : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(16), 0, 32356843Sdim Align(16)) {} 33356843Sdim 34356843Sdimvoid VEFrameLowering::emitPrologueInsns(MachineFunction &MF, 35356843Sdim MachineBasicBlock &MBB, 36356843Sdim MachineBasicBlock::iterator MBBI, 37356843Sdim int NumBytes, 38356843Sdim bool RequireFPUpdate) const { 39356843Sdim 40356843Sdim DebugLoc dl; 41356843Sdim const VEInstrInfo &TII = 42356843Sdim *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo()); 43356843Sdim // Insert following codes here as prologue 44356843Sdim // 45356843Sdim // st %fp, 0(,%sp) 46356843Sdim // st %lr, 8(,%sp) 47356843Sdim // st %got, 24(,%sp) 48356843Sdim // st %plt, 32(,%sp) 49356843Sdim // or %fp, 0, %sp 50356843Sdim 51356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) 52356843Sdim .addReg(VE::SX11) 53356843Sdim .addImm(0) 54356843Sdim .addReg(VE::SX9); 55356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) 56356843Sdim .addReg(VE::SX11) 57356843Sdim .addImm(8) 58356843Sdim .addReg(VE::SX10); 59356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) 60356843Sdim .addReg(VE::SX11) 61356843Sdim .addImm(24) 62356843Sdim .addReg(VE::SX15); 63356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) 64356843Sdim .addReg(VE::SX11) 65356843Sdim .addImm(32) 66356843Sdim .addReg(VE::SX16); 67356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX9) 68356843Sdim .addReg(VE::SX11) 69356843Sdim .addImm(0); 70356843Sdim} 71356843Sdim 72356843Sdimvoid VEFrameLowering::emitEpilogueInsns(MachineFunction &MF, 73356843Sdim MachineBasicBlock &MBB, 74356843Sdim MachineBasicBlock::iterator MBBI, 75356843Sdim int NumBytes, 76356843Sdim bool RequireFPUpdate) const { 77356843Sdim 78356843Sdim DebugLoc dl; 79356843Sdim const VEInstrInfo &TII = 80356843Sdim *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo()); 81356843Sdim // Insert following codes here as epilogue 82356843Sdim // 83356843Sdim // or %sp, 0, %fp 84356843Sdim // ld %got, 32(,%sp) 85356843Sdim // ld %plt, 24(,%sp) 86356843Sdim // ld %lr, 8(,%sp) 87356843Sdim // ld %fp, 0(,%sp) 88356843Sdim 89356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX11) 90356843Sdim .addReg(VE::SX9) 91356843Sdim .addImm(0); 92356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX16) 93356843Sdim .addReg(VE::SX11) 94356843Sdim .addImm(32); 95356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX15) 96356843Sdim .addReg(VE::SX11) 97356843Sdim .addImm(24); 98356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX10) 99356843Sdim .addReg(VE::SX11) 100356843Sdim .addImm(8); 101356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX9) 102356843Sdim .addReg(VE::SX11) 103356843Sdim .addImm(0); 104356843Sdim} 105356843Sdim 106356843Sdimvoid VEFrameLowering::emitSPAdjustment(MachineFunction &MF, 107356843Sdim MachineBasicBlock &MBB, 108356843Sdim MachineBasicBlock::iterator MBBI, 109356843Sdim int NumBytes) const { 110356843Sdim DebugLoc dl; 111356843Sdim const VEInstrInfo &TII = 112356843Sdim *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo()); 113356843Sdim 114356843Sdim if (NumBytes >= -64 && NumBytes < 63) { 115356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::ADXri), VE::SX11) 116356843Sdim .addReg(VE::SX11) 117356843Sdim .addImm(NumBytes); 118356843Sdim return; 119356843Sdim } 120356843Sdim 121356843Sdim // Emit following codes. This clobbers SX13 which we always know is 122356843Sdim // available here. 123356843Sdim // lea %s13,%lo(NumBytes) 124356843Sdim // and %s13,%s13,(32)0 125356843Sdim // lea.sl %sp,%hi(NumBytes)(%sp, %s13) 126356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::LEAzzi), VE::SX13) 127356843Sdim .addImm(LO32(NumBytes)); 128356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::ANDrm0), VE::SX13) 129356843Sdim .addReg(VE::SX13) 130356843Sdim .addImm(32); 131356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::LEASLrri), VE::SX11) 132356843Sdim .addReg(VE::SX11) 133356843Sdim .addReg(VE::SX13) 134356843Sdim .addImm(HI32(NumBytes)); 135356843Sdim} 136356843Sdim 137356843Sdimvoid VEFrameLowering::emitSPExtend(MachineFunction &MF, MachineBasicBlock &MBB, 138356843Sdim MachineBasicBlock::iterator MBBI, 139356843Sdim int NumBytes) const { 140356843Sdim DebugLoc dl; 141356843Sdim const VEInstrInfo &TII = 142356843Sdim *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo()); 143356843Sdim 144356843Sdim // Emit following codes. It is not possible to insert multiple 145356843Sdim // BasicBlocks in PEI pass, so we emit two pseudo instructions here. 146356843Sdim // 147356843Sdim // EXTEND_STACK // pseudo instrcution 148356843Sdim // EXTEND_STACK_GUARD // pseudo instrcution 149356843Sdim // 150356843Sdim // EXTEND_STACK pseudo will be converted by ExpandPostRA pass into 151356843Sdim // following instructions with multiple basic blocks later. 152356843Sdim // 153356843Sdim // thisBB: 154356843Sdim // brge.l.t %sp, %sl, sinkBB 155356843Sdim // syscallBB: 156356843Sdim // ld %s61, 0x18(, %tp) // load param area 157356843Sdim // or %s62, 0, %s0 // spill the value of %s0 158356843Sdim // lea %s63, 0x13b // syscall # of grow 159356843Sdim // shm.l %s63, 0x0(%s61) // store syscall # at addr:0 160356843Sdim // shm.l %sl, 0x8(%s61) // store old limit at addr:8 161356843Sdim // shm.l %sp, 0x10(%s61) // store new limit at addr:16 162356843Sdim // monc // call monitor 163356843Sdim // or %s0, 0, %s62 // restore the value of %s0 164356843Sdim // sinkBB: 165356843Sdim // 166356843Sdim // EXTEND_STACK_GUARD pseudo will be simply eliminated by ExpandPostRA 167356843Sdim // pass. This pseudo is required to be at the next of EXTEND_STACK 168356843Sdim // pseudo in order to protect iteration loop in ExpandPostRA. 169356843Sdim 170356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK)); 171356843Sdim BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK_GUARD)); 172356843Sdim} 173356843Sdim 174356843Sdimvoid VEFrameLowering::emitPrologue(MachineFunction &MF, 175356843Sdim MachineBasicBlock &MBB) const { 176356843Sdim assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); 177356843Sdim MachineFrameInfo &MFI = MF.getFrameInfo(); 178356843Sdim const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>(); 179356843Sdim const VEInstrInfo &TII = 180356843Sdim *static_cast<const VEInstrInfo *>(Subtarget.getInstrInfo()); 181356843Sdim const VERegisterInfo &RegInfo = 182356843Sdim *static_cast<const VERegisterInfo *>(Subtarget.getRegisterInfo()); 183356843Sdim MachineBasicBlock::iterator MBBI = MBB.begin(); 184356843Sdim // Debug location must be unknown since the first debug location is used 185356843Sdim // to determine the end of the prologue. 186356843Sdim DebugLoc dl; 187356843Sdim bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF); 188356843Sdim 189356843Sdim // FIXME: unfortunately, returning false from canRealignStack 190356843Sdim // actually just causes needsStackRealignment to return false, 191356843Sdim // rather than reporting an error, as would be sensible. This is 192356843Sdim // poor, but fixing that bogosity is going to be a large project. 193356843Sdim // For now, just see if it's lied, and report an error here. 194356843Sdim if (!NeedsStackRealignment && MFI.getMaxAlignment() > getStackAlignment()) 195356843Sdim report_fatal_error("Function \"" + Twine(MF.getName()) + 196356843Sdim "\" required " 197356843Sdim "stack re-alignment, but LLVM couldn't handle it " 198356843Sdim "(probably because it has a dynamic alloca)."); 199356843Sdim 200356843Sdim // Get the number of bytes to allocate from the FrameInfo 201356843Sdim int NumBytes = (int)MFI.getStackSize(); 202356843Sdim // The VE ABI requires a reserved 176-byte area in the user's stack, starting 203356843Sdim // at %sp + 16. This is for the callee Register Save Area (RSA). 204356843Sdim // 205356843Sdim // We therefore need to add that offset to the total stack size 206356843Sdim // after all the stack objects are placed by 207356843Sdim // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack 208356843Sdim // needs to be aligned *after* the extra size is added, we need to disable 209356843Sdim // calculateFrameObjectOffsets's built-in stack alignment, by having 210356843Sdim // targetHandlesStackFrameRounding return true. 211356843Sdim 212356843Sdim // Add the extra call frame stack size, if needed. (This is the same 213356843Sdim // code as in PrologEpilogInserter, but also gets disabled by 214356843Sdim // targetHandlesStackFrameRounding) 215356843Sdim if (MFI.adjustsStack() && hasReservedCallFrame(MF)) 216356843Sdim NumBytes += MFI.getMaxCallFrameSize(); 217356843Sdim 218356843Sdim // Adds the VE subtarget-specific spill area to the stack 219356843Sdim // size. Also ensures target-required alignment. 220356843Sdim NumBytes = Subtarget.getAdjustedFrameSize(NumBytes); 221356843Sdim 222356843Sdim // Finally, ensure that the size is sufficiently aligned for the 223356843Sdim // data on the stack. 224356843Sdim if (MFI.getMaxAlignment() > 0) { 225356843Sdim NumBytes = alignTo(NumBytes, MFI.getMaxAlignment()); 226356843Sdim } 227356843Sdim 228356843Sdim // Update stack size with corrected value. 229356843Sdim MFI.setStackSize(NumBytes); 230356843Sdim 231356843Sdim // Emit Prologue instructions to save %lr 232356843Sdim emitPrologueInsns(MF, MBB, MBBI, NumBytes, true); 233356843Sdim 234356843Sdim // Emit stack adjust instructions 235356843Sdim emitSPAdjustment(MF, MBB, MBBI, -NumBytes); 236356843Sdim 237356843Sdim // Emit stack extend instructions 238356843Sdim emitSPExtend(MF, MBB, MBBI, -NumBytes); 239356843Sdim 240356843Sdim unsigned regFP = RegInfo.getDwarfRegNum(VE::SX9, true); 241356843Sdim 242356843Sdim // Emit ".cfi_def_cfa_register 30". 243356843Sdim unsigned CFIIndex = 244356843Sdim MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, regFP)); 245356843Sdim BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 246356843Sdim .addCFIIndex(CFIIndex); 247356843Sdim 248356843Sdim // Emit ".cfi_window_save". 249356843Sdim CFIIndex = MF.addFrameInst(MCCFIInstruction::createWindowSave(nullptr)); 250356843Sdim BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 251356843Sdim .addCFIIndex(CFIIndex); 252356843Sdim} 253356843Sdim 254356843SdimMachineBasicBlock::iterator VEFrameLowering::eliminateCallFramePseudoInstr( 255356843Sdim MachineFunction &MF, MachineBasicBlock &MBB, 256356843Sdim MachineBasicBlock::iterator I) const { 257356843Sdim if (!hasReservedCallFrame(MF)) { 258356843Sdim MachineInstr &MI = *I; 259356843Sdim int Size = MI.getOperand(0).getImm(); 260356843Sdim if (MI.getOpcode() == VE::ADJCALLSTACKDOWN) 261356843Sdim Size = -Size; 262356843Sdim 263356843Sdim if (Size) 264356843Sdim emitSPAdjustment(MF, MBB, I, Size); 265356843Sdim } 266356843Sdim return MBB.erase(I); 267356843Sdim} 268356843Sdim 269356843Sdimvoid VEFrameLowering::emitEpilogue(MachineFunction &MF, 270356843Sdim MachineBasicBlock &MBB) const { 271356843Sdim MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 272356843Sdim DebugLoc dl = MBBI->getDebugLoc(); 273356843Sdim MachineFrameInfo &MFI = MF.getFrameInfo(); 274356843Sdim 275356843Sdim int NumBytes = (int)MFI.getStackSize(); 276356843Sdim 277356843Sdim // Emit Epilogue instructions to restore %lr 278356843Sdim emitEpilogueInsns(MF, MBB, MBBI, NumBytes, true); 279356843Sdim} 280356843Sdim 281356843Sdimbool VEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { 282356843Sdim // Reserve call frame if there are no variable sized objects on the stack. 283356843Sdim return !MF.getFrameInfo().hasVarSizedObjects(); 284356843Sdim} 285356843Sdim 286356843Sdim// hasFP - Return true if the specified function should have a dedicated frame 287356843Sdim// pointer register. This is true if the function has variable sized allocas or 288356843Sdim// if frame pointer elimination is disabled. 289356843Sdimbool VEFrameLowering::hasFP(const MachineFunction &MF) const { 290356843Sdim const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); 291356843Sdim 292356843Sdim const MachineFrameInfo &MFI = MF.getFrameInfo(); 293356843Sdim return MF.getTarget().Options.DisableFramePointerElim(MF) || 294356843Sdim RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() || 295356843Sdim MFI.isFrameAddressTaken(); 296356843Sdim} 297356843Sdim 298356843Sdimint VEFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, 299356843Sdim unsigned &FrameReg) const { 300356843Sdim // Addressable stack objects are accessed using neg. offsets from 301356843Sdim // %fp, or positive offsets from %sp. 302356843Sdim int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI); 303356843Sdim FrameReg = VE::SX11; // %sp 304356843Sdim return FrameOffset + MF.getFrameInfo().getStackSize(); 305356843Sdim} 306356843Sdim 307356843Sdimbool VEFrameLowering::isLeafProc(MachineFunction &MF) const { 308356843Sdim 309356843Sdim MachineRegisterInfo &MRI = MF.getRegInfo(); 310356843Sdim MachineFrameInfo &MFI = MF.getFrameInfo(); 311356843Sdim 312356843Sdim return !MFI.hasCalls() // No calls 313356843Sdim && !MRI.isPhysRegUsed(VE::SX18) // Registers within limits 314356843Sdim // (s18 is first CSR) 315356843Sdim && !MRI.isPhysRegUsed(VE::SX11) // %sp un-used 316356843Sdim && !hasFP(MF); // Don't need %fp 317356843Sdim} 318356843Sdim 319356843Sdimvoid VEFrameLowering::determineCalleeSaves(MachineFunction &MF, 320356843Sdim BitVector &SavedRegs, 321356843Sdim RegScavenger *RS) const { 322356843Sdim TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 323356843Sdim 324356843Sdim assert(isLeafProc(MF) && "TODO implement for non-leaf procs"); 325356843Sdim} 326