1//===-- LoongArchFrameLowering.cpp - LoongArch Frame Information -*- C++ -*-==//
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 LoongArch implementation of TargetFrameLowering class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "LoongArchFrameLowering.h"
14#include "LoongArchMachineFunctionInfo.h"
15#include "LoongArchSubtarget.h"
16#include "MCTargetDesc/LoongArchBaseInfo.h"
17#include "MCTargetDesc/LoongArchMCTargetDesc.h"
18#include "llvm/CodeGen/CFIInstBuilder.h"
19#include "llvm/CodeGen/LivePhysRegs.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/MachineRegisterInfo.h"
24#include "llvm/CodeGen/RegisterScavenging.h"
25#include "llvm/IR/DiagnosticInfo.h"
26#include "llvm/MC/MCDwarf.h"
27
28using namespace llvm;
29
30#define DEBUG_TYPE "loongarch-frame-lowering"
31
32// Return true if the specified function should have a dedicated frame
33// pointer register. This is true if frame pointer elimination is
34// disabled, if it needs dynamic stack realignment, if the function has
35// variable sized allocas, or if the frame address is taken.
36bool LoongArchFrameLowering::hasFPImpl(const MachineFunction &MF) const {
37 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
38
39 const MachineFrameInfo &MFI = MF.getFrameInfo();
40 return MF.disableFramePointerElim() || RegInfo->hasStackRealignment(MF) ||
41 MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken();
42}
43
44bool LoongArchFrameLowering::hasBP(const MachineFunction &MF) const {
45 const MachineFrameInfo &MFI = MF.getFrameInfo();
46 const TargetRegisterInfo *TRI = STI.getRegisterInfo();
47
48 return MFI.hasVarSizedObjects() && TRI->hasStackRealignment(MF);
49}
50
51void LoongArchFrameLowering::adjustReg(MachineBasicBlock &MBB,
52 MachineBasicBlock::iterator MBBI,
53 const DebugLoc &DL, Register DestReg,
54 Register SrcReg, int64_t Val,
55 MachineInstr::MIFlag Flag) const {
56 const LoongArchInstrInfo *TII = STI.getInstrInfo();
57 bool IsLA64 = STI.is64Bit();
58 unsigned Addi = IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W;
59
60 if (DestReg == SrcReg && Val == 0)
61 return;
62
63 if (isInt<12>(x: Val)) {
64 // addi.w/d $DstReg, $SrcReg, Val
65 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: Addi), DestReg)
66 .addReg(RegNo: SrcReg)
67 .addImm(Val)
68 .setMIFlag(Flag);
69 return;
70 }
71
72 // Try to split the offset across two ADDIs. We need to keep the stack pointer
73 // aligned after each ADDI. We need to determine the maximum value we can put
74 // in each ADDI. In the negative direction, we can use -2048 which is always
75 // sufficiently aligned. In the positive direction, we need to find the
76 // largest 12-bit immediate that is aligned. Exclude -4096 since it can be
77 // created with LU12I.W.
78 assert(getStackAlign().value() < 2048 && "Stack alignment too large");
79 int64_t MaxPosAdjStep = 2048 - getStackAlign().value();
80 if (Val > -4096 && Val <= (2 * MaxPosAdjStep)) {
81 int64_t FirstAdj = Val < 0 ? -2048 : MaxPosAdjStep;
82 Val -= FirstAdj;
83 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: Addi), DestReg)
84 .addReg(RegNo: SrcReg)
85 .addImm(Val: FirstAdj)
86 .setMIFlag(Flag);
87 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: Addi), DestReg)
88 .addReg(RegNo: DestReg, Flags: RegState::Kill)
89 .addImm(Val)
90 .setMIFlag(Flag);
91 return;
92 }
93
94 unsigned Opc = IsLA64 ? LoongArch::ADD_D : LoongArch::ADD_W;
95 if (Val < 0) {
96 Val = -Val;
97 Opc = IsLA64 ? LoongArch::SUB_D : LoongArch::SUB_W;
98 }
99
100 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
101 Register ScratchReg = MRI.createVirtualRegister(RegClass: &LoongArch::GPRRegClass);
102 TII->movImm(MBB, MBBI, DL, DstReg: ScratchReg, Val, Flag);
103 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: Opc), DestReg)
104 .addReg(RegNo: SrcReg)
105 .addReg(RegNo: ScratchReg, Flags: RegState::Kill)
106 .setMIFlag(Flag);
107}
108
109// Determine the size of the frame and maximum call frame size.
110void LoongArchFrameLowering::determineFrameLayout(MachineFunction &MF) const {
111 MachineFrameInfo &MFI = MF.getFrameInfo();
112
113 // Get the number of bytes to allocate from the FrameInfo.
114 uint64_t FrameSize = MFI.getStackSize();
115
116 // Make sure the frame is aligned.
117 FrameSize = alignTo(Size: FrameSize, A: getStackAlign());
118
119 // Update frame info.
120 MFI.setStackSize(FrameSize);
121}
122
123static uint64_t estimateFunctionSizeInBytes(const LoongArchInstrInfo *TII,
124 const MachineFunction &MF) {
125 uint64_t FuncSize = 0;
126 for (auto &MBB : MF)
127 for (auto &MI : MBB)
128 FuncSize += TII->getInstSizeInBytes(MI);
129 return FuncSize;
130}
131
132static bool needScavSlotForCFR(MachineFunction &MF) {
133 if (!MF.getSubtarget<LoongArchSubtarget>().hasBasicF())
134 return false;
135 for (auto &MBB : MF)
136 for (auto &MI : MBB)
137 if (MI.getOpcode() == LoongArch::PseudoST_CFR)
138 return true;
139 return false;
140}
141
142void LoongArchFrameLowering::processFunctionBeforeFrameFinalized(
143 MachineFunction &MF, RegScavenger *RS) const {
144 const LoongArchRegisterInfo *RI = STI.getRegisterInfo();
145 const TargetRegisterClass &RC = LoongArch::GPRRegClass;
146 const LoongArchInstrInfo *TII = STI.getInstrInfo();
147 LoongArchMachineFunctionInfo *LAFI =
148 MF.getInfo<LoongArchMachineFunctionInfo>();
149 MachineFrameInfo &MFI = MF.getFrameInfo();
150
151 unsigned ScavSlotsNum = 0;
152
153 // Far branches beyond 27-bit offset require a spill slot for scratch
154 // register.
155 bool IsLargeFunction = !isInt<27>(x: estimateFunctionSizeInBytes(TII, MF));
156 if (IsLargeFunction)
157 ScavSlotsNum = 1;
158
159 // estimateStackSize has been observed to under-estimate the final stack
160 // size, so give ourselves wiggle-room by checking for stack size
161 // representable an 11-bit signed field rather than 12-bits.
162 // For [x]vstelm.{b/h/w/d} memory instructions with 8 imm offset, 7-bit
163 // signed field is fine.
164 unsigned EstimateStackSize = MFI.estimateStackSize(MF);
165 if (!isInt<11>(x: EstimateStackSize) ||
166 (MF.getSubtarget<LoongArchSubtarget>().hasExtLSX() &&
167 !isInt<7>(x: EstimateStackSize)))
168 ScavSlotsNum = std::max(a: ScavSlotsNum, b: 1u);
169
170 // For CFR spill.
171 if (needScavSlotForCFR(MF))
172 ++ScavSlotsNum;
173
174 // Create emergency spill slots.
175 for (unsigned i = 0; i < ScavSlotsNum; ++i) {
176 int FI =
177 MFI.CreateSpillStackObject(Size: RI->getSpillSize(RC), Alignment: RI->getSpillAlign(RC));
178 RS->addScavengingFrameIndex(FI);
179 if (IsLargeFunction && LAFI->getBranchRelaxationSpillFrameIndex() == -1)
180 LAFI->setBranchRelaxationSpillFrameIndex(FI);
181 LLVM_DEBUG(dbgs() << "Allocated FI(" << FI
182 << ") as the emergency spill slot.\n");
183 }
184}
185
186// Allocate stack space and probe it if necessary.
187void LoongArchFrameLowering::allocateStack(MachineBasicBlock &MBB,
188 MachineBasicBlock::iterator MBBI,
189 MachineFunction &MF, uint64_t Offset,
190 uint64_t RealStackSize, bool EmitCFI,
191 bool NeedProbe, uint64_t ProbeSize,
192 bool DynAllocation,
193 MachineInstr::MIFlag Flag) const {
194 DebugLoc DL;
195 const LoongArchInstrInfo *TII = STI.getInstrInfo();
196 const bool IsLA64 = STI.is64Bit();
197 const Register SPReg = LoongArch::R3;
198 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
199
200 // Simply allocate the stack if it's not big enough to require a probe.
201 if (!NeedProbe || Offset <= ProbeSize) {
202 adjustReg(MBB, MBBI, DL, DestReg: SPReg, SrcReg: SPReg, Val: -Offset, Flag);
203 if (EmitCFI)
204 CFIBuilder.buildDefCFAOffset(Offset: RealStackSize);
205
206 if (NeedProbe && DynAllocation) {
207 // st.{w/d} $zero, $sp, 0
208 BuildMI(BB&: MBB, I: MBBI, MIMD: DL,
209 MCID: TII->get(Opcode: IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
210 .addReg(RegNo: LoongArch::R0)
211 .addReg(RegNo: SPReg)
212 .addImm(Val: 0)
213 .setMIFlag(Flag);
214 }
215
216 return;
217 }
218
219 // Unroll the probe loop depending on the number of iterations.
220 if (Offset < ProbeSize * 5) {
221 const uint64_t CFAAdjust = RealStackSize - Offset;
222
223 uint64_t CurrentOffset = 0;
224 while (CurrentOffset + ProbeSize <= Offset) {
225 adjustReg(MBB, MBBI, DL, DestReg: SPReg, SrcReg: SPReg, Val: -ProbeSize, Flag);
226 // st.{w/d} $zero, $sp, 0
227 BuildMI(BB&: MBB, I: MBBI, MIMD: DL,
228 MCID: TII->get(Opcode: IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
229 .addReg(RegNo: LoongArch::R0)
230 .addReg(RegNo: SPReg)
231 .addImm(Val: 0)
232 .setMIFlag(Flag);
233
234 CurrentOffset += ProbeSize;
235 if (EmitCFI)
236 CFIBuilder.buildDefCFAOffset(Offset: CurrentOffset + CFAAdjust);
237 }
238
239 const uint64_t Residual = Offset - CurrentOffset;
240 if (Residual) {
241 adjustReg(MBB, MBBI, DL, DestReg: SPReg, SrcReg: SPReg, Val: -Residual, Flag);
242 if (EmitCFI)
243 CFIBuilder.buildDefCFAOffset(Offset: RealStackSize);
244
245 if (DynAllocation) {
246 // st.{w/d} $zero, $sp, 0
247 BuildMI(BB&: MBB, I: MBBI, MIMD: DL,
248 MCID: TII->get(Opcode: IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
249 .addReg(RegNo: LoongArch::R0)
250 .addReg(RegNo: SPReg)
251 .addImm(Val: 0)
252 .setMIFlag(Flag);
253 }
254 }
255 return;
256 }
257
258 // Emit a variable-length allocation probing loop.
259 const uint64_t RoundedSize = alignDown(Value: Offset, Align: ProbeSize);
260 const uint64_t Residual = Offset - RoundedSize;
261 const uint64_t CFAAdjust = RealStackSize - Offset;
262
263 const Register TargetReg = LoongArch::R13;
264 // SUB TargetReg, $sp, RoundedSize
265 adjustReg(MBB, MBBI, DL, DestReg: TargetReg, SrcReg: SPReg, Val: -RoundedSize, Flag);
266
267 if (EmitCFI) {
268 // Set the CFA register to TargetReg.
269 CFIBuilder.buildDefCFA(Reg: TargetReg, Offset: RoundedSize + CFAAdjust);
270 }
271
272 // It will be expanded to a probe loop in inlineStackProbe().
273 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::PROBED_STACKALLOC))
274 .addReg(RegNo: TargetReg);
275
276 if (EmitCFI) {
277 // Set the CFA register back to SP.
278 CFIBuilder.buildDefCFARegister(Reg: SPReg);
279 }
280
281 if (Residual) {
282 adjustReg(MBB, MBBI, DL, DestReg: SPReg, SrcReg: SPReg, Val: -Residual, Flag);
283 if (DynAllocation) {
284 // st.{w/d} $zero, $sp, 0
285 BuildMI(BB&: MBB, I: MBBI, MIMD: DL,
286 MCID: TII->get(Opcode: IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
287 .addReg(RegNo: LoongArch::R0)
288 .addReg(RegNo: SPReg)
289 .addImm(Val: 0)
290 .setMIFlag(Flag);
291 }
292 }
293
294 if (EmitCFI)
295 CFIBuilder.buildDefCFAOffset(Offset: RealStackSize);
296}
297
298void LoongArchFrameLowering::emitPrologue(MachineFunction &MF,
299 MachineBasicBlock &MBB) const {
300 MachineFrameInfo &MFI = MF.getFrameInfo();
301 auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>();
302 const LoongArchRegisterInfo *RI = STI.getRegisterInfo();
303 const LoongArchInstrInfo *TII = STI.getInstrInfo();
304 MachineBasicBlock::iterator MBBI = MBB.begin();
305 bool IsLA64 = STI.is64Bit();
306
307 Register SPReg = LoongArch::R3;
308 Register FPReg = LoongArch::R22;
309
310 // Debug location must be unknown since the first debug location is used
311 // to determine the end of the prologue.
312 DebugLoc DL;
313 // All calls are tail calls in GHC calling conv, and functions have no
314 // prologue/epilogue.
315 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
316 return;
317 // Determine the correct frame layout
318 determineFrameLayout(MF);
319
320 // First, compute final stack size.
321 uint64_t StackSize = MFI.getStackSize();
322 uint64_t RealStackSize = StackSize;
323
324 // Early exit if there is no need to allocate space in the stack.
325 if (StackSize == 0 && !MFI.adjustsStack())
326 return;
327
328 uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
329 // Split the SP adjustment to reduce the offsets of callee saved spill.
330 if (FirstSPAdjustAmount)
331 StackSize = FirstSPAdjustAmount;
332
333 // Adjust stack.
334 const LoongArchTargetLowering *TLI = STI.getTargetLowering();
335 const bool NeedProbe = TLI->hasInlineStackProbe(MF);
336 const uint64_t ProbeSize = TLI->getStackProbeSize(MF, StackAlign: getStackAlign());
337 const bool DynAllocation =
338 MF.getInfo<LoongArchMachineFunctionInfo>()->hasDynamicAllocation();
339 if (StackSize != 0)
340 allocateStack(MBB, MBBI, MF, Offset: StackSize, RealStackSize: StackSize,
341 /*EmitCFI=*/true, NeedProbe, ProbeSize, DynAllocation,
342 Flag: MachineInstr::FrameSetup);
343
344 const auto &CSI = MFI.getCalleeSavedInfo();
345
346 // The frame pointer is callee-saved, and code has been generated for us to
347 // save it to the stack. We need to skip over the storing of callee-saved
348 // registers as the frame pointer must be modified after it has been saved
349 // to the stack, not before.
350 std::advance(i&: MBBI, n: CSI.size());
351
352 // Iterate over list of callee-saved registers and emit .cfi_offset
353 // directives.
354 for (const auto &Entry : CSI) {
355 int64_t Offset = MFI.getObjectOffset(ObjectIdx: Entry.getFrameIdx());
356 unsigned CFIIndex = MF.addFrameInst(Inst: MCCFIInstruction::createOffset(
357 L: nullptr, Register: RI->getDwarfRegNum(Reg: Entry.getReg(), isEH: true), Offset));
358 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: TargetOpcode::CFI_INSTRUCTION))
359 .addCFIIndex(CFIIndex)
360 .setMIFlag(MachineInstr::FrameSetup);
361 }
362
363 // Generate new FP.
364 if (hasFP(MF)) {
365 adjustReg(MBB, MBBI, DL, DestReg: FPReg, SrcReg: SPReg,
366 Val: StackSize - LoongArchFI->getVarArgsSaveSize(),
367 Flag: MachineInstr::FrameSetup);
368
369 // Emit ".cfi_def_cfa $fp, LoongArchFI->getVarArgsSaveSize()"
370 unsigned CFIIndex = MF.addFrameInst(
371 Inst: MCCFIInstruction::cfiDefCfa(L: nullptr, Register: RI->getDwarfRegNum(Reg: FPReg, isEH: true),
372 Offset: LoongArchFI->getVarArgsSaveSize()));
373 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: TargetOpcode::CFI_INSTRUCTION))
374 .addCFIIndex(CFIIndex)
375 .setMIFlag(MachineInstr::FrameSetup);
376 }
377
378 // Emit the second SP adjustment after saving callee saved registers.
379 if (FirstSPAdjustAmount) {
380 uint64_t SecondSPAdjustAmount = RealStackSize - FirstSPAdjustAmount;
381 assert(SecondSPAdjustAmount > 0 &&
382 "SecondSPAdjustAmount should be greater than zero");
383 allocateStack(MBB, MBBI, MF, Offset: SecondSPAdjustAmount, RealStackSize,
384 EmitCFI: !hasFP(MF), NeedProbe, ProbeSize, DynAllocation,
385 Flag: MachineInstr::FrameSetup);
386 }
387
388 if (hasFP(MF)) {
389 // Realign stack.
390 if (RI->hasStackRealignment(MF)) {
391 unsigned Align = Log2(A: MFI.getMaxAlign());
392 assert(Align > 0 && "The stack realignment size is invalid!");
393 BuildMI(BB&: MBB, I: MBBI, MIMD: DL,
394 MCID: TII->get(Opcode: IsLA64 ? LoongArch::BSTRINS_D : LoongArch::BSTRINS_W),
395 DestReg: SPReg)
396 .addReg(RegNo: SPReg)
397 .addReg(RegNo: LoongArch::R0)
398 .addImm(Val: Align - 1)
399 .addImm(Val: 0)
400 .setMIFlag(MachineInstr::FrameSetup);
401 // FP will be used to restore the frame in the epilogue, so we need
402 // another base register BP to record SP after re-alignment. SP will
403 // track the current stack after allocating variable sized objects.
404 if (hasBP(MF)) {
405 // move BP, $sp
406 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: LoongArch::OR),
407 DestReg: LoongArchABI::getBPReg())
408 .addReg(RegNo: SPReg)
409 .addReg(RegNo: LoongArch::R0)
410 .setMIFlag(MachineInstr::FrameSetup);
411 }
412 }
413 }
414}
415
416void LoongArchFrameLowering::emitEpilogue(MachineFunction &MF,
417 MachineBasicBlock &MBB) const {
418 const LoongArchRegisterInfo *RI = STI.getRegisterInfo();
419 MachineFrameInfo &MFI = MF.getFrameInfo();
420 auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>();
421 Register SPReg = LoongArch::R3;
422 // All calls are tail calls in GHC calling conv, and functions have no
423 // prologue/epilogue.
424 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
425 return;
426 MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
427 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
428
429 const auto &CSI = MFI.getCalleeSavedInfo();
430 // Skip to before the restores of callee-saved registers.
431 auto LastFrameDestroy = MBBI;
432 if (!CSI.empty())
433 LastFrameDestroy = std::prev(x: MBBI, n: CSI.size());
434
435 // Get the number of bytes from FrameInfo.
436 uint64_t StackSize = MFI.getStackSize();
437
438 // Restore the stack pointer.
439 if (RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects()) {
440 assert(hasFP(MF) && "frame pointer should not have been eliminated");
441 adjustReg(MBB, MBBI: LastFrameDestroy, DL, DestReg: SPReg, SrcReg: LoongArch::R22,
442 Val: -StackSize + LoongArchFI->getVarArgsSaveSize(),
443 Flag: MachineInstr::FrameDestroy);
444 }
445
446 uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
447 if (FirstSPAdjustAmount) {
448 uint64_t SecondSPAdjustAmount = StackSize - FirstSPAdjustAmount;
449 assert(SecondSPAdjustAmount > 0 &&
450 "SecondSPAdjustAmount should be greater than zero");
451
452 adjustReg(MBB, MBBI: LastFrameDestroy, DL, DestReg: SPReg, SrcReg: SPReg, Val: SecondSPAdjustAmount,
453 Flag: MachineInstr::FrameDestroy);
454 StackSize = FirstSPAdjustAmount;
455 }
456
457 // Deallocate stack
458 adjustReg(MBB, MBBI, DL, DestReg: SPReg, SrcReg: SPReg, Val: StackSize, Flag: MachineInstr::FrameDestroy);
459}
460
461// Synthesize the probe loop.
462static void emitStackProbeInline(MachineBasicBlock::iterator MBBI, DebugLoc DL,
463 Register TargetReg) {
464 assert(TargetReg != LoongArch::R3 &&
465 "New top of stack cannot already be in $sp");
466
467 MachineBasicBlock &MBB = *MBBI->getParent();
468 MachineFunction &MF = *MBB.getParent();
469
470 const LoongArchSubtarget &STI = MF.getSubtarget<LoongArchSubtarget>();
471 const LoongArchInstrInfo *TII = STI.getInstrInfo();
472 const bool IsLA64 = STI.is64Bit();
473 const Align StackAlign = STI.getFrameLowering()->getStackAlign();
474 const LoongArchTargetLowering *TLI = STI.getTargetLowering();
475 const uint64_t ProbeSize = TLI->getStackProbeSize(MF, StackAlign);
476
477 MachineFunction::iterator MBBInsertPoint = std::next(x: MBB.getIterator());
478 MachineBasicBlock *LoopTestMBB =
479 MF.CreateMachineBasicBlock(BB: MBB.getBasicBlock());
480 MF.insert(MBBI: MBBInsertPoint, MBB: LoopTestMBB);
481 MachineBasicBlock *ExitMBB = MF.CreateMachineBasicBlock(BB: MBB.getBasicBlock());
482 MF.insert(MBBI: MBBInsertPoint, MBB: ExitMBB);
483 const Register SPReg = LoongArch::R3;
484 const Register ScratchReg = LoongArch::R14;
485 const MachineInstr::MIFlag Flags = MachineInstr::FrameSetup;
486
487 // ScratchReg = ProbeSize
488 TII->movImm(MBB, MBBI, DL, DstReg: ScratchReg, Val: ProbeSize, Flag: Flags);
489
490 // LoopTest:
491 // sub.{w/d} $sp, $sp, ScratchReg
492 BuildMI(BB&: *LoopTestMBB, I: LoopTestMBB->end(), MIMD: DL,
493 MCID: TII->get(Opcode: IsLA64 ? LoongArch::SUB_D : LoongArch::SUB_W), DestReg: SPReg)
494 .addReg(RegNo: SPReg)
495 .addReg(RegNo: ScratchReg)
496 .setMIFlag(Flags);
497
498 // st.{w/d} $zero, $sp, 0
499 BuildMI(BB&: *LoopTestMBB, I: LoopTestMBB->end(), MIMD: DL,
500 MCID: TII->get(Opcode: IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
501 .addReg(RegNo: LoongArch::R0)
502 .addReg(RegNo: SPReg)
503 .addImm(Val: 0)
504 .setMIFlag(Flags);
505
506 // bne $sp, TargetReg, LoopTest
507 BuildMI(BB&: *LoopTestMBB, I: LoopTestMBB->end(), MIMD: DL, MCID: TII->get(Opcode: LoongArch::BNE))
508 .addReg(RegNo: SPReg)
509 .addReg(RegNo: TargetReg)
510 .addMBB(MBB: LoopTestMBB)
511 .setMIFlag(Flags);
512
513 ExitMBB->splice(Where: ExitMBB->end(), Other: &MBB, From: std::next(x: MBBI), To: MBB.end());
514 ExitMBB->transferSuccessorsAndUpdatePHIs(FromMBB: &MBB);
515
516 LoopTestMBB->addSuccessor(Succ: ExitMBB);
517 LoopTestMBB->addSuccessor(Succ: LoopTestMBB);
518 MBB.addSuccessor(Succ: LoopTestMBB);
519 // Update liveins.
520 fullyRecomputeLiveIns(MBBs: {ExitMBB, LoopTestMBB});
521}
522
523void LoongArchFrameLowering::inlineStackProbe(MachineFunction &MF,
524 MachineBasicBlock &MBB) const {
525 // Get the instructions that need to be replaced. We emit at most two of
526 // these. Remember them in order to avoid complications coming from the need
527 // to traverse the block while potentially creating more blocks.
528 SmallVector<MachineInstr *, 2> ToReplace;
529 for (MachineInstr &MI : MBB) {
530 if (MI.getOpcode() == LoongArch::PROBED_STACKALLOC) {
531 ToReplace.push_back(Elt: &MI);
532 }
533 }
534
535 for (MachineInstr *MI : ToReplace) {
536 MachineBasicBlock::iterator MBBI = MI->getIterator();
537 DebugLoc DL = MBB.findDebugLoc(MBBI);
538 Register TargetReg = MI->getOperand(i: 0).getReg();
539 emitStackProbeInline(MBBI, DL, TargetReg);
540 MBBI->eraseFromParent();
541 }
542}
543
544// We would like to split the SP adjustment to reduce prologue/epilogue
545// as following instructions. In this way, the offset of the callee saved
546// register could fit in a single store.
547// e.g.
548// addi.d $sp, $sp, -2032
549// st.d $ra, $sp, 2024
550// st.d $fp, $sp, 2016
551// addi.d $sp, $sp, -16
552uint64_t LoongArchFrameLowering::getFirstSPAdjustAmount(
553 const MachineFunction &MF) const {
554 const MachineFrameInfo &MFI = MF.getFrameInfo();
555 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
556
557 // Return the FirstSPAdjustAmount if the StackSize can not fit in a signed
558 // 12-bit and there exists a callee-saved register needing to be pushed.
559 if (!isInt<12>(x: MFI.getStackSize()) && (CSI.size() > 0)) {
560 // FirstSPAdjustAmount is chosen as (2048 - StackAlign) because 2048 will
561 // cause sp = sp + 2048 in the epilogue to be split into multiple
562 // instructions. Offsets smaller than 2048 can fit in a single load/store
563 // instruction, and we have to stick with the stack alignment.
564 // So (2048 - StackAlign) will satisfy the stack alignment.
565 return 2048 - getStackAlign().value();
566 }
567 return 0;
568}
569
570void LoongArchFrameLowering::determineCalleeSaves(MachineFunction &MF,
571 BitVector &SavedRegs,
572 RegScavenger *RS) const {
573 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
574 // Unconditionally spill RA and FP only if the function uses a frame
575 // pointer.
576 if (hasFP(MF)) {
577 SavedRegs.set(LoongArch::R1);
578 SavedRegs.set(LoongArch::R22);
579 }
580 // Mark BP as used if function has dedicated base pointer.
581 if (hasBP(MF))
582 SavedRegs.set(LoongArchABI::getBPReg());
583}
584
585// Do not preserve stack space within prologue for outgoing variables if the
586// function contains variable size objects.
587// Let eliminateCallFramePseudoInstr preserve stack space for it.
588bool LoongArchFrameLowering::hasReservedCallFrame(
589 const MachineFunction &MF) const {
590 return !MF.getFrameInfo().hasVarSizedObjects();
591}
592
593// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions.
594MachineBasicBlock::iterator
595LoongArchFrameLowering::eliminateCallFramePseudoInstr(
596 MachineFunction &MF, MachineBasicBlock &MBB,
597 MachineBasicBlock::iterator MI) const {
598 Register SPReg = LoongArch::R3;
599 DebugLoc DL = MI->getDebugLoc();
600
601 if (!hasReservedCallFrame(MF)) {
602 // If space has not been reserved for a call frame, ADJCALLSTACKDOWN and
603 // ADJCALLSTACKUP must be converted to instructions manipulating the stack
604 // pointer. This is necessary when there is a variable length stack
605 // allocation (e.g. alloca), which means it's not possible to allocate
606 // space for outgoing arguments from within the function prologue.
607 int64_t Amount = MI->getOperand(i: 0).getImm();
608
609 if (Amount != 0) {
610 // Ensure the stack remains aligned after adjustment.
611 Amount = alignSPAdjust(SPAdj: Amount);
612
613 if (MI->getOpcode() == LoongArch::ADJCALLSTACKDOWN)
614 Amount = -Amount;
615
616 const LoongArchTargetLowering *TLI =
617 MF.getSubtarget<LoongArchSubtarget>().getTargetLowering();
618 const int64_t ProbeSize = TLI->getStackProbeSize(MF, StackAlign: getStackAlign());
619 if (TLI->hasInlineStackProbe(MF) && -Amount >= ProbeSize) {
620 // When stack probing is enabled, the decrement of SP may need to be
621 // probed. We can handle both the decrement and the probing in
622 // allocateStack.
623 const bool DynAllocation =
624 MF.getInfo<LoongArchMachineFunctionInfo>()->hasDynamicAllocation();
625 allocateStack(MBB, MBBI: MI, MF, Offset: -Amount, RealStackSize: -Amount,
626 EmitCFI: MF.needsFrameMoves() && !hasFP(MF),
627 /*NeedProbe=*/true, ProbeSize, DynAllocation,
628 Flag: MachineInstr::NoFlags);
629 inlineStackProbe(MF, MBB);
630 } else {
631 adjustReg(MBB, MBBI: MI, DL, DestReg: SPReg, SrcReg: SPReg, Val: Amount, Flag: MachineInstr::NoFlags);
632 }
633 }
634 }
635
636 return MBB.erase(I: MI);
637}
638
639bool LoongArchFrameLowering::spillCalleeSavedRegisters(
640 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
641 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
642 if (CSI.empty())
643 return true;
644
645 MachineFunction *MF = MBB.getParent();
646 const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
647
648 // Insert the spill to the stack frame.
649 for (auto &CS : CSI) {
650 MCRegister Reg = CS.getReg();
651 // If the register is RA and the return address is taken by method
652 // LoongArchTargetLowering::lowerRETURNADDR, don't set kill flag.
653 bool IsKill =
654 !(Reg == LoongArch::R1 && MF->getFrameInfo().isReturnAddressTaken());
655 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
656 TII.storeRegToStackSlot(MBB, MI, SrcReg: Reg, isKill: IsKill, FrameIndex: CS.getFrameIdx(), RC,
657 VReg: Register());
658 }
659
660 return true;
661}
662
663StackOffset LoongArchFrameLowering::getFrameIndexReference(
664 const MachineFunction &MF, int FI, Register &FrameReg) const {
665 const MachineFrameInfo &MFI = MF.getFrameInfo();
666 const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();
667 auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>();
668 uint64_t StackSize = MFI.getStackSize();
669 uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
670
671 // Callee-saved registers should be referenced relative to the stack
672 // pointer (positive offset), otherwise use the frame pointer (negative
673 // offset).
674 const auto &CSI = MFI.getCalleeSavedInfo();
675 int MinCSFI = 0;
676 int MaxCSFI = -1;
677 StackOffset Offset =
678 StackOffset::getFixed(Fixed: MFI.getObjectOffset(ObjectIdx: FI) - getOffsetOfLocalArea() +
679 MFI.getOffsetAdjustment());
680
681 if (CSI.size()) {
682 MinCSFI = CSI[0].getFrameIdx();
683 MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
684 }
685
686 if (FI >= MinCSFI && FI <= MaxCSFI) {
687 FrameReg = LoongArch::R3;
688 if (FirstSPAdjustAmount)
689 Offset += StackOffset::getFixed(Fixed: FirstSPAdjustAmount);
690 else
691 Offset += StackOffset::getFixed(Fixed: StackSize);
692 } else if (RI->hasStackRealignment(MF) && !MFI.isFixedObjectIndex(ObjectIdx: FI)) {
693 // If the stack was realigned, the frame pointer is set in order to allow
694 // SP to be restored, so we need another base register to record the stack
695 // after realignment.
696 FrameReg = hasBP(MF) ? LoongArchABI::getBPReg() : LoongArch::R3;
697 Offset += StackOffset::getFixed(Fixed: StackSize);
698 } else {
699 FrameReg = RI->getFrameRegister(MF);
700 if (hasFP(MF))
701 Offset += StackOffset::getFixed(Fixed: LoongArchFI->getVarArgsSaveSize());
702 else
703 Offset += StackOffset::getFixed(Fixed: StackSize);
704 }
705
706 return Offset;
707}
708
709bool LoongArchFrameLowering::enableShrinkWrapping(
710 const MachineFunction &MF) const {
711 // Keep the conventional code flow when not optimizing.
712 if (MF.getFunction().hasOptNone())
713 return false;
714
715 return true;
716}
717