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