1 //===-- VEFrameLowering.cpp - VE 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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the VE implementation of TargetFrameLowering class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "VEFrameLowering.h"
14 #include "VEInstrInfo.h"
15 #include "VESubtarget.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/CodeGen/RegisterScavenging.h"
22 #include "llvm/IR/DataLayout.h"
23 #include "llvm/IR/Function.h"
24 #include "llvm/Support/CommandLine.h"
25 #include "llvm/Target/TargetOptions.h"
26 #include "llvm/Support/MathExtras.h"
27 
28 using namespace llvm;
29 
30 VEFrameLowering::VEFrameLowering(const VESubtarget &ST)
31     : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(16), 0,
32                           Align(16)) {}
33 
34 void VEFrameLowering::emitPrologueInsns(MachineFunction &MF,
35                                         MachineBasicBlock &MBB,
36                                         MachineBasicBlock::iterator MBBI,
37                                         int NumBytes,
38                                         bool RequireFPUpdate) const {
39 
40   DebugLoc dl;
41   const VEInstrInfo &TII =
42       *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
43   // Insert following codes here as prologue
44   //
45   //    st %fp, 0(,%sp)
46   //    st %lr, 8(,%sp)
47   //    st %got, 24(,%sp)
48   //    st %plt, 32(,%sp)
49   //    or %fp, 0, %sp
50 
51   BuildMI(MBB, MBBI, dl, TII.get(VE::STSri))
52       .addReg(VE::SX11)
53       .addImm(0)
54       .addReg(VE::SX9);
55   BuildMI(MBB, MBBI, dl, TII.get(VE::STSri))
56       .addReg(VE::SX11)
57       .addImm(8)
58       .addReg(VE::SX10);
59   BuildMI(MBB, MBBI, dl, TII.get(VE::STSri))
60       .addReg(VE::SX11)
61       .addImm(24)
62       .addReg(VE::SX15);
63   BuildMI(MBB, MBBI, dl, TII.get(VE::STSri))
64       .addReg(VE::SX11)
65       .addImm(32)
66       .addReg(VE::SX16);
67   BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX9)
68       .addReg(VE::SX11)
69       .addImm(0);
70 }
71 
72 void VEFrameLowering::emitEpilogueInsns(MachineFunction &MF,
73                                         MachineBasicBlock &MBB,
74                                         MachineBasicBlock::iterator MBBI,
75                                         int NumBytes,
76                                         bool RequireFPUpdate) const {
77 
78   DebugLoc dl;
79   const VEInstrInfo &TII =
80       *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
81   // Insert following codes here as epilogue
82   //
83   //    or %sp, 0, %fp
84   //    ld %got, 32(,%sp)
85   //    ld %plt, 24(,%sp)
86   //    ld %lr, 8(,%sp)
87   //    ld %fp, 0(,%sp)
88 
89   BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX11)
90       .addReg(VE::SX9)
91       .addImm(0);
92   BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX16)
93       .addReg(VE::SX11)
94       .addImm(32);
95   BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX15)
96       .addReg(VE::SX11)
97       .addImm(24);
98   BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX10)
99       .addReg(VE::SX11)
100       .addImm(8);
101   BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX9)
102       .addReg(VE::SX11)
103       .addImm(0);
104 }
105 
106 void VEFrameLowering::emitSPAdjustment(MachineFunction &MF,
107                                        MachineBasicBlock &MBB,
108                                        MachineBasicBlock::iterator MBBI,
109                                        int NumBytes) const {
110   DebugLoc dl;
111   const VEInstrInfo &TII =
112       *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
113 
114   if (NumBytes >= -64 && NumBytes < 63) {
115     BuildMI(MBB, MBBI, dl, TII.get(VE::ADXri), VE::SX11)
116         .addReg(VE::SX11)
117         .addImm(NumBytes);
118     return;
119   }
120 
121   // Emit following codes.  This clobbers SX13 which we always know is
122   // available here.
123   //   lea     %s13,%lo(NumBytes)
124   //   and     %s13,%s13,(32)0
125   //   lea.sl  %sp,%hi(NumBytes)(%sp, %s13)
126   BuildMI(MBB, MBBI, dl, TII.get(VE::LEAzzi), VE::SX13)
127       .addImm(LO32(NumBytes));
128   BuildMI(MBB, MBBI, dl, TII.get(VE::ANDrm0), VE::SX13)
129       .addReg(VE::SX13)
130       .addImm(32);
131   BuildMI(MBB, MBBI, dl, TII.get(VE::LEASLrri), VE::SX11)
132       .addReg(VE::SX11)
133       .addReg(VE::SX13)
134       .addImm(HI32(NumBytes));
135 }
136 
137 void VEFrameLowering::emitSPExtend(MachineFunction &MF, MachineBasicBlock &MBB,
138                                    MachineBasicBlock::iterator MBBI,
139                                    int NumBytes) const {
140   DebugLoc dl;
141   const VEInstrInfo &TII =
142       *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
143 
144   // Emit following codes.  It is not possible to insert multiple
145   // BasicBlocks in PEI pass, so we emit two pseudo instructions here.
146   //
147   //   EXTEND_STACK                     // pseudo instrcution
148   //   EXTEND_STACK_GUARD               // pseudo instrcution
149   //
150   // EXTEND_STACK pseudo will be converted by ExpandPostRA pass into
151   // following instructions with multiple basic blocks later.
152   //
153   // thisBB:
154   //   brge.l.t %sp, %sl, sinkBB
155   // syscallBB:
156   //   ld      %s61, 0x18(, %tp)        // load param area
157   //   or      %s62, 0, %s0             // spill the value of %s0
158   //   lea     %s63, 0x13b              // syscall # of grow
159   //   shm.l   %s63, 0x0(%s61)          // store syscall # at addr:0
160   //   shm.l   %sl, 0x8(%s61)           // store old limit at addr:8
161   //   shm.l   %sp, 0x10(%s61)          // store new limit at addr:16
162   //   monc                             // call monitor
163   //   or      %s0, 0, %s62             // restore the value of %s0
164   // sinkBB:
165   //
166   // EXTEND_STACK_GUARD pseudo will be simply eliminated by ExpandPostRA
167   // pass.  This pseudo is required to be at the next of EXTEND_STACK
168   // pseudo in order to protect iteration loop in ExpandPostRA.
169 
170   BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK));
171   BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK_GUARD));
172 }
173 
174 void VEFrameLowering::emitPrologue(MachineFunction &MF,
175                                    MachineBasicBlock &MBB) const {
176   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
177   MachineFrameInfo &MFI = MF.getFrameInfo();
178   const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>();
179   const VEInstrInfo &TII =
180       *static_cast<const VEInstrInfo *>(Subtarget.getInstrInfo());
181   const VERegisterInfo &RegInfo =
182       *static_cast<const VERegisterInfo *>(Subtarget.getRegisterInfo());
183   MachineBasicBlock::iterator MBBI = MBB.begin();
184   // Debug location must be unknown since the first debug location is used
185   // to determine the end of the prologue.
186   DebugLoc dl;
187   bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF);
188 
189   // FIXME: unfortunately, returning false from canRealignStack
190   // actually just causes needsStackRealignment to return false,
191   // rather than reporting an error, as would be sensible. This is
192   // poor, but fixing that bogosity is going to be a large project.
193   // For now, just see if it's lied, and report an error here.
194   if (!NeedsStackRealignment && MFI.getMaxAlignment() > getStackAlignment())
195     report_fatal_error("Function \"" + Twine(MF.getName()) +
196                        "\" required "
197                        "stack re-alignment, but LLVM couldn't handle it "
198                        "(probably because it has a dynamic alloca).");
199 
200   // Get the number of bytes to allocate from the FrameInfo
201   int NumBytes = (int)MFI.getStackSize();
202   // The VE ABI requires a reserved 176-byte area in the user's stack, starting
203   // at %sp + 16. This is for the callee Register Save Area (RSA).
204   //
205   // We therefore need to add that offset to the total stack size
206   // after all the stack objects are placed by
207   // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack
208   // needs to be aligned *after* the extra size is added, we need to disable
209   // calculateFrameObjectOffsets's built-in stack alignment, by having
210   // targetHandlesStackFrameRounding return true.
211 
212   // Add the extra call frame stack size, if needed. (This is the same
213   // code as in PrologEpilogInserter, but also gets disabled by
214   // targetHandlesStackFrameRounding)
215   if (MFI.adjustsStack() && hasReservedCallFrame(MF))
216     NumBytes += MFI.getMaxCallFrameSize();
217 
218   // Adds the VE subtarget-specific spill area to the stack
219   // size. Also ensures target-required alignment.
220   NumBytes = Subtarget.getAdjustedFrameSize(NumBytes);
221 
222   // Finally, ensure that the size is sufficiently aligned for the
223   // data on the stack.
224   if (MFI.getMaxAlignment() > 0) {
225     NumBytes = alignTo(NumBytes, MFI.getMaxAlignment());
226   }
227 
228   // Update stack size with corrected value.
229   MFI.setStackSize(NumBytes);
230 
231   // Emit Prologue instructions to save %lr
232   emitPrologueInsns(MF, MBB, MBBI, NumBytes, true);
233 
234   // Emit stack adjust instructions
235   emitSPAdjustment(MF, MBB, MBBI, -NumBytes);
236 
237   // Emit stack extend instructions
238   emitSPExtend(MF, MBB, MBBI, -NumBytes);
239 
240   unsigned regFP = RegInfo.getDwarfRegNum(VE::SX9, true);
241 
242   // Emit ".cfi_def_cfa_register 30".
243   unsigned CFIIndex =
244       MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, regFP));
245   BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
246       .addCFIIndex(CFIIndex);
247 
248   // Emit ".cfi_window_save".
249   CFIIndex = MF.addFrameInst(MCCFIInstruction::createWindowSave(nullptr));
250   BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
251       .addCFIIndex(CFIIndex);
252 }
253 
254 MachineBasicBlock::iterator VEFrameLowering::eliminateCallFramePseudoInstr(
255     MachineFunction &MF, MachineBasicBlock &MBB,
256     MachineBasicBlock::iterator I) const {
257   if (!hasReservedCallFrame(MF)) {
258     MachineInstr &MI = *I;
259     int Size = MI.getOperand(0).getImm();
260     if (MI.getOpcode() == VE::ADJCALLSTACKDOWN)
261       Size = -Size;
262 
263     if (Size)
264       emitSPAdjustment(MF, MBB, I, Size);
265   }
266   return MBB.erase(I);
267 }
268 
269 void VEFrameLowering::emitEpilogue(MachineFunction &MF,
270                                    MachineBasicBlock &MBB) const {
271   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
272   DebugLoc dl = MBBI->getDebugLoc();
273   MachineFrameInfo &MFI = MF.getFrameInfo();
274 
275   int NumBytes = (int)MFI.getStackSize();
276 
277   // Emit Epilogue instructions to restore %lr
278   emitEpilogueInsns(MF, MBB, MBBI, NumBytes, true);
279 }
280 
281 bool VEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
282   // Reserve call frame if there are no variable sized objects on the stack.
283   return !MF.getFrameInfo().hasVarSizedObjects();
284 }
285 
286 // hasFP - Return true if the specified function should have a dedicated frame
287 // pointer register.  This is true if the function has variable sized allocas or
288 // if frame pointer elimination is disabled.
289 bool VEFrameLowering::hasFP(const MachineFunction &MF) const {
290   const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
291 
292   const MachineFrameInfo &MFI = MF.getFrameInfo();
293   return MF.getTarget().Options.DisableFramePointerElim(MF) ||
294          RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() ||
295          MFI.isFrameAddressTaken();
296 }
297 
298 int VEFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
299                                             unsigned &FrameReg) const {
300   // Addressable stack objects are accessed using neg. offsets from
301   // %fp, or positive offsets from %sp.
302   int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI);
303   FrameReg = VE::SX11; // %sp
304   return FrameOffset + MF.getFrameInfo().getStackSize();
305 }
306 
307 bool VEFrameLowering::isLeafProc(MachineFunction &MF) const {
308 
309   MachineRegisterInfo &MRI = MF.getRegInfo();
310   MachineFrameInfo &MFI = MF.getFrameInfo();
311 
312   return !MFI.hasCalls()                 // No calls
313          && !MRI.isPhysRegUsed(VE::SX18) // Registers within limits
314                                          //   (s18 is first CSR)
315          && !MRI.isPhysRegUsed(VE::SX11) // %sp un-used
316          && !hasFP(MF);                  // Don't need %fp
317 }
318 
319 void VEFrameLowering::determineCalleeSaves(MachineFunction &MF,
320                                            BitVector &SavedRegs,
321                                            RegScavenger *RS) const {
322   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
323 
324   assert(isLeafProc(MF) && "TODO implement for non-leaf procs");
325 }
326