RISCVFrameLowering.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. //===-- RISCVFrameLowering.cpp - RISCV 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 RISCV implementation of TargetFrameLowering class.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "RISCVFrameLowering.h"
  13. #include "RISCVMachineFunctionInfo.h"
  14. #include "RISCVSubtarget.h"
  15. #include "llvm/CodeGen/MachineFrameInfo.h"
  16. #include "llvm/CodeGen/MachineFunction.h"
  17. #include "llvm/CodeGen/MachineInstrBuilder.h"
  18. #include "llvm/CodeGen/MachineRegisterInfo.h"
  19. #include "llvm/CodeGen/RegisterScavenging.h"
  20. #include "llvm/MC/MCDwarf.h"
  21. using namespace llvm;
  22. bool RISCVFrameLowering::hasFP(const MachineFunction &MF) const {
  23. const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
  24. const MachineFrameInfo &MFI = MF.getFrameInfo();
  25. return MF.getTarget().Options.DisableFramePointerElim(MF) ||
  26. RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() ||
  27. MFI.isFrameAddressTaken();
  28. }
  29. // Determines the size of the frame and maximum call frame size.
  30. void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const {
  31. MachineFrameInfo &MFI = MF.getFrameInfo();
  32. const RISCVRegisterInfo *RI = STI.getRegisterInfo();
  33. // Get the number of bytes to allocate from the FrameInfo.
  34. uint64_t FrameSize = MFI.getStackSize();
  35. // Get the alignment.
  36. unsigned StackAlign = getStackAlignment();
  37. if (RI->needsStackRealignment(MF)) {
  38. unsigned MaxStackAlign = std::max(StackAlign, MFI.getMaxAlignment());
  39. FrameSize += (MaxStackAlign - StackAlign);
  40. StackAlign = MaxStackAlign;
  41. }
  42. // Set Max Call Frame Size
  43. uint64_t MaxCallSize = alignTo(MFI.getMaxCallFrameSize(), StackAlign);
  44. MFI.setMaxCallFrameSize(MaxCallSize);
  45. // Make sure the frame is aligned.
  46. FrameSize = alignTo(FrameSize, StackAlign);
  47. // Update frame info.
  48. MFI.setStackSize(FrameSize);
  49. }
  50. void RISCVFrameLowering::adjustReg(MachineBasicBlock &MBB,
  51. MachineBasicBlock::iterator MBBI,
  52. const DebugLoc &DL, Register DestReg,
  53. Register SrcReg, int64_t Val,
  54. MachineInstr::MIFlag Flag) const {
  55. MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
  56. const RISCVInstrInfo *TII = STI.getInstrInfo();
  57. if (DestReg == SrcReg && Val == 0)
  58. return;
  59. if (isInt<12>(Val)) {
  60. BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg)
  61. .addReg(SrcReg)
  62. .addImm(Val)
  63. .setMIFlag(Flag);
  64. } else {
  65. unsigned Opc = RISCV::ADD;
  66. bool isSub = Val < 0;
  67. if (isSub) {
  68. Val = -Val;
  69. Opc = RISCV::SUB;
  70. }
  71. Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
  72. TII->movImm(MBB, MBBI, DL, ScratchReg, Val, Flag);
  73. BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
  74. .addReg(SrcReg)
  75. .addReg(ScratchReg, RegState::Kill)
  76. .setMIFlag(Flag);
  77. }
  78. }
  79. // Returns the register used to hold the frame pointer.
  80. static Register getFPReg(const RISCVSubtarget &STI) { return RISCV::X8; }
  81. // Returns the register used to hold the stack pointer.
  82. static Register getSPReg(const RISCVSubtarget &STI) { return RISCV::X2; }
  83. void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
  84. MachineBasicBlock &MBB) const {
  85. assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
  86. MachineFrameInfo &MFI = MF.getFrameInfo();
  87. auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
  88. const RISCVRegisterInfo *RI = STI.getRegisterInfo();
  89. const RISCVInstrInfo *TII = STI.getInstrInfo();
  90. MachineBasicBlock::iterator MBBI = MBB.begin();
  91. if (RI->needsStackRealignment(MF) && MFI.hasVarSizedObjects()) {
  92. report_fatal_error(
  93. "RISC-V backend can't currently handle functions that need stack "
  94. "realignment and have variable sized objects");
  95. }
  96. Register FPReg = getFPReg(STI);
  97. Register SPReg = getSPReg(STI);
  98. // Debug location must be unknown since the first debug location is used
  99. // to determine the end of the prologue.
  100. DebugLoc DL;
  101. // Determine the correct frame layout
  102. determineFrameLayout(MF);
  103. // FIXME (note copied from Lanai): This appears to be overallocating. Needs
  104. // investigation. Get the number of bytes to allocate from the FrameInfo.
  105. uint64_t StackSize = MFI.getStackSize();
  106. // Early exit if there is no need to allocate on the stack
  107. if (StackSize == 0 && !MFI.adjustsStack())
  108. return;
  109. uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
  110. // Split the SP adjustment to reduce the offsets of callee saved spill.
  111. if (FirstSPAdjustAmount)
  112. StackSize = FirstSPAdjustAmount;
  113. // Allocate space on the stack if necessary.
  114. adjustReg(MBB, MBBI, DL, SPReg, SPReg, -StackSize, MachineInstr::FrameSetup);
  115. // Emit ".cfi_def_cfa_offset StackSize"
  116. unsigned CFIIndex = MF.addFrameInst(
  117. MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize));
  118. BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
  119. .addCFIIndex(CFIIndex);
  120. // The frame pointer is callee-saved, and code has been generated for us to
  121. // save it to the stack. We need to skip over the storing of callee-saved
  122. // registers as the frame pointer must be modified after it has been saved
  123. // to the stack, not before.
  124. // FIXME: assumes exactly one instruction is used to save each callee-saved
  125. // register.
  126. const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
  127. std::advance(MBBI, CSI.size());
  128. // Iterate over list of callee-saved registers and emit .cfi_offset
  129. // directives.
  130. for (const auto &Entry : CSI) {
  131. int64_t Offset = MFI.getObjectOffset(Entry.getFrameIdx());
  132. Register Reg = Entry.getReg();
  133. unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
  134. nullptr, RI->getDwarfRegNum(Reg, true), Offset));
  135. BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
  136. .addCFIIndex(CFIIndex);
  137. }
  138. // Generate new FP.
  139. if (hasFP(MF)) {
  140. adjustReg(MBB, MBBI, DL, FPReg, SPReg,
  141. StackSize - RVFI->getVarArgsSaveSize(), MachineInstr::FrameSetup);
  142. // Emit ".cfi_def_cfa $fp, 0"
  143. unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa(
  144. nullptr, RI->getDwarfRegNum(FPReg, true), 0));
  145. BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
  146. .addCFIIndex(CFIIndex);
  147. }
  148. // Emit the second SP adjustment after saving callee saved registers.
  149. if (FirstSPAdjustAmount) {
  150. uint64_t SecondSPAdjustAmount = MFI.getStackSize() - FirstSPAdjustAmount;
  151. assert(SecondSPAdjustAmount > 0 &&
  152. "SecondSPAdjustAmount should be greater than zero");
  153. adjustReg(MBB, MBBI, DL, SPReg, SPReg, -SecondSPAdjustAmount,
  154. MachineInstr::FrameSetup);
  155. // Emit ".cfi_def_cfa_offset StackSize"
  156. unsigned CFIIndex = MF.addFrameInst(
  157. MCCFIInstruction::createDefCfaOffset(nullptr, -MFI.getStackSize()));
  158. BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
  159. .addCFIIndex(CFIIndex);
  160. }
  161. if (hasFP(MF)) {
  162. // Realign Stack
  163. const RISCVRegisterInfo *RI = STI.getRegisterInfo();
  164. if (RI->needsStackRealignment(MF)) {
  165. unsigned MaxAlignment = MFI.getMaxAlignment();
  166. const RISCVInstrInfo *TII = STI.getInstrInfo();
  167. if (isInt<12>(-(int)MaxAlignment)) {
  168. BuildMI(MBB, MBBI, DL, TII->get(RISCV::ANDI), SPReg)
  169. .addReg(SPReg)
  170. .addImm(-(int)MaxAlignment);
  171. } else {
  172. unsigned ShiftAmount = countTrailingZeros(MaxAlignment);
  173. Register VR =
  174. MF.getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
  175. BuildMI(MBB, MBBI, DL, TII->get(RISCV::SRLI), VR)
  176. .addReg(SPReg)
  177. .addImm(ShiftAmount);
  178. BuildMI(MBB, MBBI, DL, TII->get(RISCV::SLLI), SPReg)
  179. .addReg(VR)
  180. .addImm(ShiftAmount);
  181. }
  182. }
  183. }
  184. }
  185. void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
  186. MachineBasicBlock &MBB) const {
  187. MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
  188. const RISCVRegisterInfo *RI = STI.getRegisterInfo();
  189. MachineFrameInfo &MFI = MF.getFrameInfo();
  190. auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
  191. DebugLoc DL = MBBI->getDebugLoc();
  192. const RISCVInstrInfo *TII = STI.getInstrInfo();
  193. Register FPReg = getFPReg(STI);
  194. Register SPReg = getSPReg(STI);
  195. // Skip to before the restores of callee-saved registers
  196. // FIXME: assumes exactly one instruction is used to restore each
  197. // callee-saved register.
  198. auto LastFrameDestroy = std::prev(MBBI, MFI.getCalleeSavedInfo().size());
  199. uint64_t StackSize = MFI.getStackSize();
  200. uint64_t FPOffset = StackSize - RVFI->getVarArgsSaveSize();
  201. // Restore the stack pointer using the value of the frame pointer. Only
  202. // necessary if the stack pointer was modified, meaning the stack size is
  203. // unknown.
  204. if (RI->needsStackRealignment(MF) || MFI.hasVarSizedObjects()) {
  205. assert(hasFP(MF) && "frame pointer should not have been eliminated");
  206. adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg, -FPOffset,
  207. MachineInstr::FrameDestroy);
  208. }
  209. uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
  210. if (FirstSPAdjustAmount) {
  211. uint64_t SecondSPAdjustAmount = MFI.getStackSize() - FirstSPAdjustAmount;
  212. assert(SecondSPAdjustAmount > 0 &&
  213. "SecondSPAdjustAmount should be greater than zero");
  214. adjustReg(MBB, LastFrameDestroy, DL, SPReg, SPReg, SecondSPAdjustAmount,
  215. MachineInstr::FrameDestroy);
  216. // Emit ".cfi_def_cfa_offset FirstSPAdjustAmount"
  217. unsigned CFIIndex =
  218. MF.addFrameInst(
  219. MCCFIInstruction::createDefCfaOffset(nullptr,
  220. -FirstSPAdjustAmount));
  221. BuildMI(MBB, LastFrameDestroy, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
  222. .addCFIIndex(CFIIndex);
  223. }
  224. if (hasFP(MF)) {
  225. // To find the instruction restoring FP from stack.
  226. for (auto &I = LastFrameDestroy; I != MBBI; ++I) {
  227. if (I->mayLoad() && I->getOperand(0).isReg()) {
  228. Register DestReg = I->getOperand(0).getReg();
  229. if (DestReg == FPReg) {
  230. // If there is frame pointer, after restoring $fp registers, we
  231. // need adjust CFA to ($sp - FPOffset).
  232. // Emit ".cfi_def_cfa $sp, -FPOffset"
  233. unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa(
  234. nullptr, RI->getDwarfRegNum(SPReg, true), -FPOffset));
  235. BuildMI(MBB, std::next(I), DL,
  236. TII->get(TargetOpcode::CFI_INSTRUCTION))
  237. .addCFIIndex(CFIIndex);
  238. break;
  239. }
  240. }
  241. }
  242. }
  243. // Add CFI directives for callee-saved registers.
  244. const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
  245. // Iterate over list of callee-saved registers and emit .cfi_restore
  246. // directives.
  247. for (const auto &Entry : CSI) {
  248. Register Reg = Entry.getReg();
  249. unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createRestore(
  250. nullptr, RI->getDwarfRegNum(Reg, true)));
  251. BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
  252. .addCFIIndex(CFIIndex);
  253. }
  254. if (FirstSPAdjustAmount)
  255. StackSize = FirstSPAdjustAmount;
  256. // Deallocate stack
  257. adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy);
  258. // After restoring $sp, we need to adjust CFA to $(sp + 0)
  259. // Emit ".cfi_def_cfa_offset 0"
  260. unsigned CFIIndex =
  261. MF.addFrameInst(MCCFIInstruction::createDefCfaOffset(nullptr, 0));
  262. BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
  263. .addCFIIndex(CFIIndex);
  264. }
  265. int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF,
  266. int FI,
  267. unsigned &FrameReg) const {
  268. const MachineFrameInfo &MFI = MF.getFrameInfo();
  269. const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();
  270. const auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
  271. // Callee-saved registers should be referenced relative to the stack
  272. // pointer (positive offset), otherwise use the frame pointer (negative
  273. // offset).
  274. const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
  275. int MinCSFI = 0;
  276. int MaxCSFI = -1;
  277. int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea() +
  278. MFI.getOffsetAdjustment();
  279. uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
  280. if (CSI.size()) {
  281. MinCSFI = CSI[0].getFrameIdx();
  282. MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
  283. }
  284. if (FI >= MinCSFI && FI <= MaxCSFI) {
  285. FrameReg = RISCV::X2;
  286. if (FirstSPAdjustAmount)
  287. Offset += FirstSPAdjustAmount;
  288. else
  289. Offset += MF.getFrameInfo().getStackSize();
  290. } else if (RI->needsStackRealignment(MF)) {
  291. assert(!MFI.hasVarSizedObjects() &&
  292. "Unexpected combination of stack realignment and varsized objects");
  293. // If the stack was realigned, the frame pointer is set in order to allow
  294. // SP to be restored, but we still access stack objects using SP.
  295. FrameReg = RISCV::X2;
  296. Offset += MF.getFrameInfo().getStackSize();
  297. } else {
  298. FrameReg = RI->getFrameRegister(MF);
  299. if (hasFP(MF))
  300. Offset += RVFI->getVarArgsSaveSize();
  301. else
  302. Offset += MF.getFrameInfo().getStackSize();
  303. }
  304. return Offset;
  305. }
  306. void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF,
  307. BitVector &SavedRegs,
  308. RegScavenger *RS) const {
  309. TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
  310. // Unconditionally spill RA and FP only if the function uses a frame
  311. // pointer.
  312. if (hasFP(MF)) {
  313. SavedRegs.set(RISCV::X1);
  314. SavedRegs.set(RISCV::X8);
  315. }
  316. // If interrupt is enabled and there are calls in the handler,
  317. // unconditionally save all Caller-saved registers and
  318. // all FP registers, regardless whether they are used.
  319. MachineFrameInfo &MFI = MF.getFrameInfo();
  320. if (MF.getFunction().hasFnAttribute("interrupt") && MFI.hasCalls()) {
  321. static const MCPhysReg CSRegs[] = { RISCV::X1, /* ra */
  322. RISCV::X5, RISCV::X6, RISCV::X7, /* t0-t2 */
  323. RISCV::X10, RISCV::X11, /* a0-a1, a2-a7 */
  324. RISCV::X12, RISCV::X13, RISCV::X14, RISCV::X15, RISCV::X16, RISCV::X17,
  325. RISCV::X28, RISCV::X29, RISCV::X30, RISCV::X31, 0 /* t3-t6 */
  326. };
  327. for (unsigned i = 0; CSRegs[i]; ++i)
  328. SavedRegs.set(CSRegs[i]);
  329. if (MF.getSubtarget<RISCVSubtarget>().hasStdExtD() ||
  330. MF.getSubtarget<RISCVSubtarget>().hasStdExtF()) {
  331. // If interrupt is enabled, this list contains all FP registers.
  332. const MCPhysReg * Regs = MF.getRegInfo().getCalleeSavedRegs();
  333. for (unsigned i = 0; Regs[i]; ++i)
  334. if (RISCV::FPR32RegClass.contains(Regs[i]) ||
  335. RISCV::FPR64RegClass.contains(Regs[i]))
  336. SavedRegs.set(Regs[i]);
  337. }
  338. }
  339. }
  340. void RISCVFrameLowering::processFunctionBeforeFrameFinalized(
  341. MachineFunction &MF, RegScavenger *RS) const {
  342. const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
  343. MachineFrameInfo &MFI = MF.getFrameInfo();
  344. const TargetRegisterClass *RC = &RISCV::GPRRegClass;
  345. // estimateStackSize has been observed to under-estimate the final stack
  346. // size, so give ourselves wiggle-room by checking for stack size
  347. // representable an 11-bit signed field rather than 12-bits.
  348. // FIXME: It may be possible to craft a function with a small stack that
  349. // still needs an emergency spill slot for branch relaxation. This case
  350. // would currently be missed.
  351. if (!isInt<11>(MFI.estimateStackSize(MF))) {
  352. int RegScavFI = MFI.CreateStackObject(
  353. RegInfo->getSpillSize(*RC), RegInfo->getSpillAlignment(*RC), false);
  354. RS->addScavengingFrameIndex(RegScavFI);
  355. }
  356. }
  357. // Not preserve stack space within prologue for outgoing variables when the
  358. // function contains variable size objects and let eliminateCallFramePseudoInstr
  359. // preserve stack space for it.
  360. bool RISCVFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
  361. return !MF.getFrameInfo().hasVarSizedObjects();
  362. }
  363. // Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions.
  364. MachineBasicBlock::iterator RISCVFrameLowering::eliminateCallFramePseudoInstr(
  365. MachineFunction &MF, MachineBasicBlock &MBB,
  366. MachineBasicBlock::iterator MI) const {
  367. Register SPReg = RISCV::X2;
  368. DebugLoc DL = MI->getDebugLoc();
  369. if (!hasReservedCallFrame(MF)) {
  370. // If space has not been reserved for a call frame, ADJCALLSTACKDOWN and
  371. // ADJCALLSTACKUP must be converted to instructions manipulating the stack
  372. // pointer. This is necessary when there is a variable length stack
  373. // allocation (e.g. alloca), which means it's not possible to allocate
  374. // space for outgoing arguments from within the function prologue.
  375. int64_t Amount = MI->getOperand(0).getImm();
  376. if (Amount != 0) {
  377. // Ensure the stack remains aligned after adjustment.
  378. Amount = alignSPAdjust(Amount);
  379. if (MI->getOpcode() == RISCV::ADJCALLSTACKDOWN)
  380. Amount = -Amount;
  381. adjustReg(MBB, MI, DL, SPReg, SPReg, Amount, MachineInstr::NoFlags);
  382. }
  383. }
  384. return MBB.erase(MI);
  385. }
  386. // We would like to split the SP adjustment to reduce prologue/epilogue
  387. // as following instructions. In this way, the offset of the callee saved
  388. // register could fit in a single store.
  389. // add sp,sp,-2032
  390. // sw ra,2028(sp)
  391. // sw s0,2024(sp)
  392. // sw s1,2020(sp)
  393. // sw s3,2012(sp)
  394. // sw s4,2008(sp)
  395. // add sp,sp,-64
  396. uint64_t
  397. RISCVFrameLowering::getFirstSPAdjustAmount(const MachineFunction &MF) const {
  398. const MachineFrameInfo &MFI = MF.getFrameInfo();
  399. const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
  400. uint64_t StackSize = MFI.getStackSize();
  401. uint64_t StackAlign = getStackAlignment();
  402. // FIXME: Disable SplitSPAdjust if save-restore libcall enabled when the patch
  403. // landing. The callee saved registers will be pushed by the
  404. // save-restore libcalls, so we don't have to split the SP adjustment
  405. // in this case.
  406. //
  407. // Return the FirstSPAdjustAmount if the StackSize can not fit in signed
  408. // 12-bit and there exists a callee saved register need to be pushed.
  409. if (!isInt<12>(StackSize) && (CSI.size() > 0)) {
  410. // FirstSPAdjustAmount is choosed as (2048 - StackAlign)
  411. // because 2048 will cause sp = sp + 2048 in epilogue split into
  412. // multi-instructions. The offset smaller than 2048 can fit in signle
  413. // load/store instruction and we have to stick with the stack alignment.
  414. // 2048 is 16-byte alignment. The stack alignment for RV32 and RV64 is 16,
  415. // for RV32E is 4. So (2048 - StackAlign) will satisfy the stack alignment.
  416. return 2048 - StackAlign;
  417. }
  418. return 0;
  419. }