xref: /freebsd/contrib/llvm-project/llvm/lib/Target/VE/VEFrameLowering.cpp (revision c66ec88fed842fbaad62c30d510644ceb7bd2d71)
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 "VEMachineFunctionInfo.h"
16 #include "VESubtarget.h"
17 #include "llvm/CodeGen/MachineFrameInfo.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/CodeGen/MachineModuleInfo.h"
21 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #include "llvm/CodeGen/RegisterScavenging.h"
23 #include "llvm/IR/DataLayout.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Target/TargetOptions.h"
27 #include "llvm/Support/MathExtras.h"
28 
29 using namespace llvm;
30 
31 VEFrameLowering::VEFrameLowering(const VESubtarget &ST)
32     : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(16), 0,
33                           Align(16)),
34       STI(ST) {}
35 
36 void VEFrameLowering::emitPrologueInsns(MachineFunction &MF,
37                                         MachineBasicBlock &MBB,
38                                         MachineBasicBlock::iterator MBBI,
39                                         uint64_t NumBytes,
40                                         bool RequireFPUpdate) const {
41 
42   DebugLoc dl;
43   const VEInstrInfo &TII =
44       *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
45   // Insert following codes here as prologue
46   //
47   //    st %fp, 0(,%sp)
48   //    st %lr, 8(,%sp)
49   //    st %got, 24(,%sp)
50   //    st %plt, 32(,%sp)
51   //    st %s17, 40(,%sp) iff this function is using s17 as BP
52   //    or %fp, 0, %sp
53 
54   BuildMI(MBB, MBBI, dl, TII.get(VE::STrii))
55       .addReg(VE::SX11)
56       .addImm(0)
57       .addImm(0)
58       .addReg(VE::SX9);
59   BuildMI(MBB, MBBI, dl, TII.get(VE::STrii))
60       .addReg(VE::SX11)
61       .addImm(0)
62       .addImm(8)
63       .addReg(VE::SX10);
64   BuildMI(MBB, MBBI, dl, TII.get(VE::STrii))
65       .addReg(VE::SX11)
66       .addImm(0)
67       .addImm(24)
68       .addReg(VE::SX15);
69   BuildMI(MBB, MBBI, dl, TII.get(VE::STrii))
70       .addReg(VE::SX11)
71       .addImm(0)
72       .addImm(32)
73       .addReg(VE::SX16);
74   if (hasBP(MF))
75     BuildMI(MBB, MBBI, dl, TII.get(VE::STrii))
76         .addReg(VE::SX11)
77         .addImm(0)
78         .addImm(40)
79         .addReg(VE::SX17);
80   BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX9)
81       .addReg(VE::SX11)
82       .addImm(0);
83 }
84 
85 void VEFrameLowering::emitEpilogueInsns(MachineFunction &MF,
86                                         MachineBasicBlock &MBB,
87                                         MachineBasicBlock::iterator MBBI,
88                                         uint64_t NumBytes,
89                                         bool RequireFPUpdate) const {
90 
91   DebugLoc dl;
92   const VEInstrInfo &TII =
93       *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
94   // Insert following codes here as epilogue
95   //
96   //    or %sp, 0, %fp
97   //    ld %s17, 40(,%sp) iff this function is using s17 as BP
98   //    ld %got, 32(,%sp)
99   //    ld %plt, 24(,%sp)
100   //    ld %lr, 8(,%sp)
101   //    ld %fp, 0(,%sp)
102 
103   BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX11)
104       .addReg(VE::SX9)
105       .addImm(0);
106   if (hasBP(MF))
107     BuildMI(MBB, MBBI, dl, TII.get(VE::LDrii), VE::SX17)
108         .addReg(VE::SX11)
109         .addImm(0)
110         .addImm(40);
111   BuildMI(MBB, MBBI, dl, TII.get(VE::LDrii), VE::SX16)
112       .addReg(VE::SX11)
113       .addImm(0)
114       .addImm(32);
115   BuildMI(MBB, MBBI, dl, TII.get(VE::LDrii), VE::SX15)
116       .addReg(VE::SX11)
117       .addImm(0)
118       .addImm(24);
119   BuildMI(MBB, MBBI, dl, TII.get(VE::LDrii), VE::SX10)
120       .addReg(VE::SX11)
121       .addImm(0)
122       .addImm(8);
123   BuildMI(MBB, MBBI, dl, TII.get(VE::LDrii), VE::SX9)
124       .addReg(VE::SX11)
125       .addImm(0)
126       .addImm(0);
127 }
128 
129 void VEFrameLowering::emitSPAdjustment(MachineFunction &MF,
130                                        MachineBasicBlock &MBB,
131                                        MachineBasicBlock::iterator MBBI,
132                                        int64_t NumBytes,
133                                        MaybeAlign MaybeAlign) const {
134   DebugLoc dl;
135   const VEInstrInfo &TII =
136       *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
137 
138   if (NumBytes >= -64 && NumBytes < 63) {
139     BuildMI(MBB, MBBI, dl, TII.get(VE::ADDSLri), VE::SX11)
140         .addReg(VE::SX11)
141         .addImm(NumBytes);
142     return;
143   }
144 
145   // Emit following codes.  This clobbers SX13 which we always know is
146   // available here.
147   //   lea     %s13,%lo(NumBytes)
148   //   and     %s13,%s13,(32)0
149   //   lea.sl  %sp,%hi(NumBytes)(%sp, %s13)
150   BuildMI(MBB, MBBI, dl, TII.get(VE::LEAzii), VE::SX13)
151       .addImm(0)
152       .addImm(0)
153       .addImm(Lo_32(NumBytes));
154   BuildMI(MBB, MBBI, dl, TII.get(VE::ANDrm), VE::SX13)
155       .addReg(VE::SX13)
156       .addImm(M0(32));
157   BuildMI(MBB, MBBI, dl, TII.get(VE::LEASLrri), VE::SX11)
158       .addReg(VE::SX11)
159       .addReg(VE::SX13)
160       .addImm(Hi_32(NumBytes));
161 
162   if (MaybeAlign) {
163     // and %sp, %sp, Align-1
164     BuildMI(MBB, MBBI, dl, TII.get(VE::ANDrm), VE::SX11)
165         .addReg(VE::SX11)
166         .addImm(M1(64 - Log2_64(MaybeAlign.valueOrOne().value())));
167   }
168 }
169 
170 void VEFrameLowering::emitSPExtend(MachineFunction &MF, MachineBasicBlock &MBB,
171                                    MachineBasicBlock::iterator MBBI) const {
172   DebugLoc dl;
173   const VEInstrInfo &TII =
174       *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
175 
176   // Emit following codes.  It is not possible to insert multiple
177   // BasicBlocks in PEI pass, so we emit two pseudo instructions here.
178   //
179   //   EXTEND_STACK                     // pseudo instrcution
180   //   EXTEND_STACK_GUARD               // pseudo instrcution
181   //
182   // EXTEND_STACK pseudo will be converted by ExpandPostRA pass into
183   // following instructions with multiple basic blocks later.
184   //
185   // thisBB:
186   //   brge.l.t %sp, %sl, sinkBB
187   // syscallBB:
188   //   ld      %s61, 0x18(, %tp)        // load param area
189   //   or      %s62, 0, %s0             // spill the value of %s0
190   //   lea     %s63, 0x13b              // syscall # of grow
191   //   shm.l   %s63, 0x0(%s61)          // store syscall # at addr:0
192   //   shm.l   %sl, 0x8(%s61)           // store old limit at addr:8
193   //   shm.l   %sp, 0x10(%s61)          // store new limit at addr:16
194   //   monc                             // call monitor
195   //   or      %s0, 0, %s62             // restore the value of %s0
196   // sinkBB:
197   //
198   // EXTEND_STACK_GUARD pseudo will be simply eliminated by ExpandPostRA
199   // pass.  This pseudo is required to be at the next of EXTEND_STACK
200   // pseudo in order to protect iteration loop in ExpandPostRA.
201 
202   BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK));
203   BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK_GUARD));
204 }
205 
206 void VEFrameLowering::emitPrologue(MachineFunction &MF,
207                                    MachineBasicBlock &MBB) const {
208   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
209   MachineFrameInfo &MFI = MF.getFrameInfo();
210   const VEInstrInfo &TII = *STI.getInstrInfo();
211   const VERegisterInfo &RegInfo = *STI.getRegisterInfo();
212   MachineBasicBlock::iterator MBBI = MBB.begin();
213   // Debug location must be unknown since the first debug location is used
214   // to determine the end of the prologue.
215   DebugLoc dl;
216   bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF);
217 
218   // FIXME: unfortunately, returning false from canRealignStack
219   // actually just causes needsStackRealignment to return false,
220   // rather than reporting an error, as would be sensible. This is
221   // poor, but fixing that bogosity is going to be a large project.
222   // For now, just see if it's lied, and report an error here.
223   if (!NeedsStackRealignment && MFI.getMaxAlign() > getStackAlign())
224     report_fatal_error("Function \"" + Twine(MF.getName()) +
225                        "\" required "
226                        "stack re-alignment, but LLVM couldn't handle it "
227                        "(probably because it has a dynamic alloca).");
228 
229   // Get the number of bytes to allocate from the FrameInfo
230   uint64_t NumBytes = MFI.getStackSize();
231 
232   // The VE ABI requires a reserved 176 bytes area at the top
233   // of stack as described in VESubtarget.cpp.  So, we adjust it here.
234   NumBytes = STI.getAdjustedFrameSize(NumBytes);
235 
236   // Finally, ensure that the size is sufficiently aligned for the
237   // data on the stack.
238   NumBytes = alignTo(NumBytes, MFI.getMaxAlign());
239 
240   // Update stack size with corrected value.
241   MFI.setStackSize(NumBytes);
242 
243   // Emit Prologue instructions to save %lr
244   emitPrologueInsns(MF, MBB, MBBI, NumBytes, true);
245 
246   // Emit stack adjust instructions
247   MaybeAlign RuntimeAlign =
248       NeedsStackRealignment ? MaybeAlign(MFI.getMaxAlign()) : None;
249   emitSPAdjustment(MF, MBB, MBBI, -(int64_t)NumBytes, RuntimeAlign);
250 
251   if (hasBP(MF)) {
252     // Copy SP to BP.
253     BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX17)
254         .addReg(VE::SX11)
255         .addImm(0);
256   }
257 
258   // Emit stack extend instructions
259   emitSPExtend(MF, MBB, MBBI);
260 
261   Register RegFP = RegInfo.getDwarfRegNum(VE::SX9, true);
262 
263   // Emit ".cfi_def_cfa_register 30".
264   unsigned CFIIndex =
265       MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, RegFP));
266   BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
267       .addCFIIndex(CFIIndex);
268 
269   // Emit ".cfi_window_save".
270   CFIIndex = MF.addFrameInst(MCCFIInstruction::createWindowSave(nullptr));
271   BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
272       .addCFIIndex(CFIIndex);
273 }
274 
275 MachineBasicBlock::iterator VEFrameLowering::eliminateCallFramePseudoInstr(
276     MachineFunction &MF, MachineBasicBlock &MBB,
277     MachineBasicBlock::iterator I) const {
278   if (!hasReservedCallFrame(MF)) {
279     MachineInstr &MI = *I;
280     int64_t Size = MI.getOperand(0).getImm();
281     if (MI.getOpcode() == VE::ADJCALLSTACKDOWN)
282       Size = -Size;
283 
284     if (Size)
285       emitSPAdjustment(MF, MBB, I, Size);
286   }
287   return MBB.erase(I);
288 }
289 
290 void VEFrameLowering::emitEpilogue(MachineFunction &MF,
291                                    MachineBasicBlock &MBB) const {
292   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
293   DebugLoc dl = MBBI->getDebugLoc();
294   MachineFrameInfo &MFI = MF.getFrameInfo();
295 
296   uint64_t NumBytes = MFI.getStackSize();
297 
298   // Emit Epilogue instructions to restore %lr
299   emitEpilogueInsns(MF, MBB, MBBI, NumBytes, true);
300 }
301 
302 // hasFP - Return true if the specified function should have a dedicated frame
303 // pointer register.  This is true if the function has variable sized allocas
304 // or if frame pointer elimination is disabled.  For the case of VE, we don't
305 // implement FP eliminator yet, but we returns false from this function to
306 // not refer fp from generated code.
307 bool VEFrameLowering::hasFP(const MachineFunction &MF) const {
308   const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
309 
310   const MachineFrameInfo &MFI = MF.getFrameInfo();
311   return MF.getTarget().Options.DisableFramePointerElim(MF) ||
312          RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() ||
313          MFI.isFrameAddressTaken();
314 }
315 
316 bool VEFrameLowering::hasBP(const MachineFunction &MF) const {
317   const MachineFrameInfo &MFI = MF.getFrameInfo();
318   const TargetRegisterInfo *TRI = STI.getRegisterInfo();
319 
320   return MFI.hasVarSizedObjects() && TRI->needsStackRealignment(MF);
321 }
322 
323 int VEFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
324                                             Register &FrameReg) const {
325   const MachineFrameInfo &MFI = MF.getFrameInfo();
326   const VERegisterInfo *RegInfo = STI.getRegisterInfo();
327   const VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>();
328   bool isFixed = MFI.isFixedObjectIndex(FI);
329 
330   int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI);
331 
332   if (FuncInfo->isLeafProc()) {
333     // If there's a leaf proc, all offsets need to be %sp-based,
334     // because we haven't caused %fp to actually point to our frame.
335     FrameReg = VE::SX11; // %sp
336     return FrameOffset + MF.getFrameInfo().getStackSize();
337   }
338   if (RegInfo->needsStackRealignment(MF) && !isFixed) {
339     // If there is dynamic stack realignment, all local object
340     // references need to be via %sp or %s17 (bp), to take account
341     // of the re-alignment.
342     if (hasBP(MF))
343       FrameReg = VE::SX17; // %bp
344     else
345       FrameReg = VE::SX11; // %sp
346     return FrameOffset + MF.getFrameInfo().getStackSize();
347   }
348   // Finally, default to using %fp.
349   FrameReg = RegInfo->getFrameRegister(MF);
350   return FrameOffset;
351 }
352 
353 bool VEFrameLowering::isLeafProc(MachineFunction &MF) const {
354 
355   MachineRegisterInfo &MRI = MF.getRegInfo();
356   MachineFrameInfo &MFI = MF.getFrameInfo();
357 
358   return !MFI.hasCalls()                 // No calls
359          && !MRI.isPhysRegUsed(VE::SX18) // Registers within limits
360                                          //   (s18 is first CSR)
361          && !MRI.isPhysRegUsed(VE::SX11) // %sp un-used
362          && !hasFP(MF);                  // Don't need %fp
363 }
364 
365 void VEFrameLowering::determineCalleeSaves(MachineFunction &MF,
366                                            BitVector &SavedRegs,
367                                            RegScavenger *RS) const {
368   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
369 
370   if (isLeafProc(MF)) {
371     VEMachineFunctionInfo *MFI = MF.getInfo<VEMachineFunctionInfo>();
372     MFI->setLeafProc(true);
373   }
374 }
375