LoongArchFrameLowering.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  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. #include "LoongArchFrameLowering.h"
  13. #include "LoongArchMachineFunctionInfo.h"
  14. #include "LoongArchSubtarget.h"
  15. #include "MCTargetDesc/LoongArchBaseInfo.h"
  16. #include "MCTargetDesc/LoongArchMCTargetDesc.h"
  17. #include "llvm/CodeGen/MachineFrameInfo.h"
  18. #include "llvm/CodeGen/MachineFunction.h"
  19. #include "llvm/CodeGen/MachineInstrBuilder.h"
  20. #include "llvm/CodeGen/MachineRegisterInfo.h"
  21. #include "llvm/CodeGen/RegisterScavenging.h"
  22. #include "llvm/IR/DiagnosticInfo.h"
  23. #include "llvm/MC/MCDwarf.h"
  24. using namespace llvm;
  25. #define DEBUG_TYPE "loongarch-frame-lowering"
  26. // Return true if the specified function should have a dedicated frame
  27. // pointer register. This is true if frame pointer elimination is
  28. // disabled, if it needs dynamic stack realignment, if the function has
  29. // variable sized allocas, or if the frame address is taken.
  30. bool LoongArchFrameLowering::hasFP(const MachineFunction &MF) const {
  31. const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
  32. const MachineFrameInfo &MFI = MF.getFrameInfo();
  33. return MF.getTarget().Options.DisableFramePointerElim(MF) ||
  34. RegInfo->hasStackRealignment(MF) || MFI.hasVarSizedObjects() ||
  35. MFI.isFrameAddressTaken();
  36. }
  37. bool LoongArchFrameLowering::hasBP(const MachineFunction &MF) const {
  38. const MachineFrameInfo &MFI = MF.getFrameInfo();
  39. const TargetRegisterInfo *TRI = STI.getRegisterInfo();
  40. return MFI.hasVarSizedObjects() && TRI->hasStackRealignment(MF);
  41. }
  42. void LoongArchFrameLowering::adjustReg(MachineBasicBlock &MBB,
  43. MachineBasicBlock::iterator MBBI,
  44. const DebugLoc &DL, Register DestReg,
  45. Register SrcReg, int64_t Val,
  46. MachineInstr::MIFlag Flag) const {
  47. const LoongArchInstrInfo *TII = STI.getInstrInfo();
  48. bool IsLA64 = STI.is64Bit();
  49. unsigned Addi = IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W;
  50. if (DestReg == SrcReg && Val == 0)
  51. return;
  52. if (isInt<12>(Val)) {
  53. // addi.w/d $DstReg, $SrcReg, Val
  54. BuildMI(MBB, MBBI, DL, TII->get(Addi), DestReg)
  55. .addReg(SrcReg)
  56. .addImm(Val)
  57. .setMIFlag(Flag);
  58. return;
  59. }
  60. // Try to split the offset across two ADDIs. We need to keep the stack pointer
  61. // aligned after each ADDI. We need to determine the maximum value we can put
  62. // in each ADDI. In the negative direction, we can use -2048 which is always
  63. // sufficiently aligned. In the positive direction, we need to find the
  64. // largest 12-bit immediate that is aligned. Exclude -4096 since it can be
  65. // created with LU12I.W.
  66. assert(getStackAlign().value() < 2048 && "Stack alignment too large");
  67. int64_t MaxPosAdjStep = 2048 - getStackAlign().value();
  68. if (Val > -4096 && Val <= (2 * MaxPosAdjStep)) {
  69. int64_t FirstAdj = Val < 0 ? -2048 : MaxPosAdjStep;
  70. Val -= FirstAdj;
  71. BuildMI(MBB, MBBI, DL, TII->get(Addi), DestReg)
  72. .addReg(SrcReg)
  73. .addImm(FirstAdj)
  74. .setMIFlag(Flag);
  75. BuildMI(MBB, MBBI, DL, TII->get(Addi), DestReg)
  76. .addReg(DestReg, RegState::Kill)
  77. .addImm(Val)
  78. .setMIFlag(Flag);
  79. return;
  80. }
  81. unsigned Opc = IsLA64 ? LoongArch::ADD_D : LoongArch::ADD_W;
  82. if (Val < 0) {
  83. Val = -Val;
  84. Opc = IsLA64 ? LoongArch::SUB_D : LoongArch::SUB_W;
  85. }
  86. MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
  87. Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
  88. TII->movImm(MBB, MBBI, DL, ScratchReg, Val, Flag);
  89. BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
  90. .addReg(SrcReg)
  91. .addReg(ScratchReg, RegState::Kill)
  92. .setMIFlag(Flag);
  93. }
  94. // Determine the size of the frame and maximum call frame size.
  95. void LoongArchFrameLowering::determineFrameLayout(MachineFunction &MF) const {
  96. MachineFrameInfo &MFI = MF.getFrameInfo();
  97. // Get the number of bytes to allocate from the FrameInfo.
  98. uint64_t FrameSize = MFI.getStackSize();
  99. // Make sure the frame is aligned.
  100. FrameSize = alignTo(FrameSize, getStackAlign());
  101. // Update frame info.
  102. MFI.setStackSize(FrameSize);
  103. }
  104. static uint64_t estimateFunctionSizeInBytes(const LoongArchInstrInfo *TII,
  105. const MachineFunction &MF) {
  106. uint64_t FuncSize = 0;
  107. for (auto &MBB : MF)
  108. for (auto &MI : MBB)
  109. FuncSize += TII->getInstSizeInBytes(MI);
  110. return FuncSize;
  111. }
  112. static bool needScavSlotForCFR(MachineFunction &MF) {
  113. if (!MF.getSubtarget<LoongArchSubtarget>().hasBasicF())
  114. return false;
  115. for (auto &MBB : MF)
  116. for (auto &MI : MBB)
  117. if (MI.getOpcode() == LoongArch::PseudoST_CFR)
  118. return true;
  119. return false;
  120. }
  121. void LoongArchFrameLowering::processFunctionBeforeFrameFinalized(
  122. MachineFunction &MF, RegScavenger *RS) const {
  123. const LoongArchRegisterInfo *RI = STI.getRegisterInfo();
  124. const TargetRegisterClass &RC = LoongArch::GPRRegClass;
  125. const LoongArchInstrInfo *TII = STI.getInstrInfo();
  126. LoongArchMachineFunctionInfo *LAFI =
  127. MF.getInfo<LoongArchMachineFunctionInfo>();
  128. MachineFrameInfo &MFI = MF.getFrameInfo();
  129. unsigned ScavSlotsNum = 0;
  130. // Far branches beyond 27-bit offset require a spill slot for scratch register.
  131. bool IsLargeFunction = !isInt<27>(estimateFunctionSizeInBytes(TII, MF));
  132. if (IsLargeFunction)
  133. ScavSlotsNum = 1;
  134. // estimateStackSize has been observed to under-estimate the final stack
  135. // size, so give ourselves wiggle-room by checking for stack size
  136. // representable an 11-bit signed field rather than 12-bits.
  137. if (!isInt<11>(MFI.estimateStackSize(MF)))
  138. ScavSlotsNum = std::max(ScavSlotsNum, 1u);
  139. // For CFR spill.
  140. if (needScavSlotForCFR(MF))
  141. ++ScavSlotsNum;
  142. // Create emergency spill slots.
  143. for (unsigned i = 0; i < ScavSlotsNum; ++i) {
  144. int FI = MFI.CreateStackObject(RI->getSpillSize(RC), RI->getSpillAlign(RC),
  145. false);
  146. RS->addScavengingFrameIndex(FI);
  147. if (IsLargeFunction && LAFI->getBranchRelaxationSpillFrameIndex() == -1)
  148. LAFI->setBranchRelaxationSpillFrameIndex(FI);
  149. LLVM_DEBUG(dbgs() << "Allocated FI(" << FI
  150. << ") as the emergency spill slot.\n");
  151. }
  152. }
  153. void LoongArchFrameLowering::emitPrologue(MachineFunction &MF,
  154. MachineBasicBlock &MBB) const {
  155. MachineFrameInfo &MFI = MF.getFrameInfo();
  156. auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>();
  157. const LoongArchRegisterInfo *RI = STI.getRegisterInfo();
  158. const LoongArchInstrInfo *TII = STI.getInstrInfo();
  159. MachineBasicBlock::iterator MBBI = MBB.begin();
  160. bool IsLA64 = STI.is64Bit();
  161. Register SPReg = LoongArch::R3;
  162. Register FPReg = LoongArch::R22;
  163. // Debug location must be unknown since the first debug location is used
  164. // to determine the end of the prologue.
  165. DebugLoc DL;
  166. // All calls are tail calls in GHC calling conv, and functions have no
  167. // prologue/epilogue.
  168. if (MF.getFunction().getCallingConv() == CallingConv::GHC)
  169. return;
  170. // Determine the correct frame layout
  171. determineFrameLayout(MF);
  172. // First, compute final stack size.
  173. uint64_t StackSize = MFI.getStackSize();
  174. uint64_t RealStackSize = StackSize;
  175. // Early exit if there is no need to allocate space in the stack.
  176. if (StackSize == 0 && !MFI.adjustsStack())
  177. return;
  178. uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF, true);
  179. uint64_t SecondSPAdjustAmount = RealStackSize - FirstSPAdjustAmount;
  180. // Split the SP adjustment to reduce the offsets of callee saved spill.
  181. if (FirstSPAdjustAmount)
  182. StackSize = FirstSPAdjustAmount;
  183. // Adjust stack.
  184. adjustReg(MBB, MBBI, DL, SPReg, SPReg, -StackSize, MachineInstr::FrameSetup);
  185. if (FirstSPAdjustAmount != 2048 || SecondSPAdjustAmount == 0) {
  186. // Emit ".cfi_def_cfa_offset StackSize".
  187. unsigned CFIIndex =
  188. MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));
  189. BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
  190. .addCFIIndex(CFIIndex)
  191. .setMIFlag(MachineInstr::FrameSetup);
  192. }
  193. const auto &CSI = MFI.getCalleeSavedInfo();
  194. // The frame pointer is callee-saved, and code has been generated for us to
  195. // save it to the stack. We need to skip over the storing of callee-saved
  196. // registers as the frame pointer must be modified after it has been saved
  197. // to the stack, not before.
  198. std::advance(MBBI, CSI.size());
  199. // Iterate over list of callee-saved registers and emit .cfi_offset
  200. // directives.
  201. for (const auto &Entry : CSI) {
  202. int64_t Offset = MFI.getObjectOffset(Entry.getFrameIdx());
  203. unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
  204. nullptr, RI->getDwarfRegNum(Entry.getReg(), true), Offset));
  205. BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
  206. .addCFIIndex(CFIIndex)
  207. .setMIFlag(MachineInstr::FrameSetup);
  208. }
  209. // Generate new FP.
  210. if (hasFP(MF)) {
  211. adjustReg(MBB, MBBI, DL, FPReg, SPReg,
  212. StackSize - LoongArchFI->getVarArgsSaveSize(),
  213. MachineInstr::FrameSetup);
  214. // Emit ".cfi_def_cfa $fp, LoongArchFI->getVarArgsSaveSize()"
  215. unsigned CFIIndex = MF.addFrameInst(
  216. MCCFIInstruction::cfiDefCfa(nullptr, RI->getDwarfRegNum(FPReg, true),
  217. LoongArchFI->getVarArgsSaveSize()));
  218. BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
  219. .addCFIIndex(CFIIndex)
  220. .setMIFlag(MachineInstr::FrameSetup);
  221. }
  222. // Emit the second SP adjustment after saving callee saved registers.
  223. if (FirstSPAdjustAmount && SecondSPAdjustAmount) {
  224. if (hasFP(MF)) {
  225. assert(SecondSPAdjustAmount > 0 &&
  226. "SecondSPAdjustAmount should be greater than zero");
  227. adjustReg(MBB, MBBI, DL, SPReg, SPReg, -SecondSPAdjustAmount,
  228. MachineInstr::FrameSetup);
  229. } else {
  230. // FIXME: RegScavenger will place the spill instruction before the
  231. // prologue if a VReg is created in the prologue. This will pollute the
  232. // caller's stack data. Therefore, until there is better way, we just use
  233. // the `addi.w/d` instruction for stack adjustment to ensure that VReg
  234. // will not be created.
  235. for (int Val = SecondSPAdjustAmount; Val > 0; Val -= 2048)
  236. BuildMI(MBB, MBBI, DL,
  237. TII->get(IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W), SPReg)
  238. .addReg(SPReg)
  239. .addImm(Val < 2048 ? -Val : -2048)
  240. .setMIFlag(MachineInstr::FrameSetup);
  241. // If we are using a frame-pointer, and thus emitted ".cfi_def_cfa fp, 0",
  242. // don't emit an sp-based .cfi_def_cfa_offset
  243. // Emit ".cfi_def_cfa_offset RealStackSize"
  244. unsigned CFIIndex = MF.addFrameInst(
  245. MCCFIInstruction::cfiDefCfaOffset(nullptr, RealStackSize));
  246. BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
  247. .addCFIIndex(CFIIndex)
  248. .setMIFlag(MachineInstr::FrameSetup);
  249. }
  250. }
  251. if (hasFP(MF)) {
  252. // Realign stack.
  253. if (RI->hasStackRealignment(MF)) {
  254. unsigned ShiftAmount = Log2(MFI.getMaxAlign());
  255. Register VR =
  256. MF.getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
  257. BuildMI(MBB, MBBI, DL,
  258. TII->get(IsLA64 ? LoongArch::SRLI_D : LoongArch::SRLI_W), VR)
  259. .addReg(SPReg)
  260. .addImm(ShiftAmount)
  261. .setMIFlag(MachineInstr::FrameSetup);
  262. BuildMI(MBB, MBBI, DL,
  263. TII->get(IsLA64 ? LoongArch::SLLI_D : LoongArch::SLLI_W), SPReg)
  264. .addReg(VR)
  265. .addImm(ShiftAmount)
  266. .setMIFlag(MachineInstr::FrameSetup);
  267. // FP will be used to restore the frame in the epilogue, so we need
  268. // another base register BP to record SP after re-alignment. SP will
  269. // track the current stack after allocating variable sized objects.
  270. if (hasBP(MF)) {
  271. // move BP, $sp
  272. BuildMI(MBB, MBBI, DL, TII->get(LoongArch::OR),
  273. LoongArchABI::getBPReg())
  274. .addReg(SPReg)
  275. .addReg(LoongArch::R0)
  276. .setMIFlag(MachineInstr::FrameSetup);
  277. }
  278. }
  279. }
  280. }
  281. void LoongArchFrameLowering::emitEpilogue(MachineFunction &MF,
  282. MachineBasicBlock &MBB) const {
  283. const LoongArchRegisterInfo *RI = STI.getRegisterInfo();
  284. MachineFrameInfo &MFI = MF.getFrameInfo();
  285. auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>();
  286. Register SPReg = LoongArch::R3;
  287. // All calls are tail calls in GHC calling conv, and functions have no
  288. // prologue/epilogue.
  289. if (MF.getFunction().getCallingConv() == CallingConv::GHC)
  290. return;
  291. MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
  292. DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
  293. const auto &CSI = MFI.getCalleeSavedInfo();
  294. // Skip to before the restores of callee-saved registers.
  295. auto LastFrameDestroy = MBBI;
  296. if (!CSI.empty())
  297. LastFrameDestroy = std::prev(MBBI, CSI.size());
  298. // Get the number of bytes from FrameInfo.
  299. uint64_t StackSize = MFI.getStackSize();
  300. // Restore the stack pointer.
  301. if (RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects()) {
  302. assert(hasFP(MF) && "frame pointer should not have been eliminated");
  303. adjustReg(MBB, LastFrameDestroy, DL, SPReg, LoongArch::R22,
  304. -StackSize + LoongArchFI->getVarArgsSaveSize(),
  305. MachineInstr::FrameDestroy);
  306. }
  307. uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
  308. if (FirstSPAdjustAmount) {
  309. uint64_t SecondSPAdjustAmount = StackSize - FirstSPAdjustAmount;
  310. assert(SecondSPAdjustAmount > 0 &&
  311. "SecondSPAdjustAmount should be greater than zero");
  312. adjustReg(MBB, LastFrameDestroy, DL, SPReg, SPReg, SecondSPAdjustAmount,
  313. MachineInstr::FrameDestroy);
  314. StackSize = FirstSPAdjustAmount;
  315. }
  316. // Deallocate stack
  317. adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy);
  318. }
  319. // We would like to split the SP adjustment to reduce prologue/epilogue
  320. // as following instructions. In this way, the offset of the callee saved
  321. // register could fit in a single store.
  322. // e.g.
  323. // addi.d $sp, $sp, -2032
  324. // st.d $ra, $sp, 2024
  325. // st.d $fp, $sp, 2016
  326. // addi.d $sp, $sp, -16
  327. uint64_t
  328. LoongArchFrameLowering::getFirstSPAdjustAmount(const MachineFunction &MF,
  329. bool IsPrologue) const {
  330. const MachineFrameInfo &MFI = MF.getFrameInfo();
  331. const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
  332. // Return the FirstSPAdjustAmount if the StackSize can not fit in a signed
  333. // 12-bit and there exists a callee-saved register needing to be pushed.
  334. if (!isInt<12>(MFI.getStackSize())) {
  335. // FirstSPAdjustAmount is chosen as (2048 - StackAlign) because 2048 will
  336. // cause sp = sp + 2048 in the epilogue to be split into multiple
  337. // instructions. Offsets smaller than 2048 can fit in a single load/store
  338. // instruction, and we have to stick with the stack alignment.
  339. // So (2048 - StackAlign) will satisfy the stack alignment.
  340. //
  341. // FIXME: This place may seem odd. When using multiple ADDI instructions to
  342. // adjust the stack in Prologue, and there are no callee-saved registers, we
  343. // can take advantage of the logic of split sp ajustment to reduce code
  344. // changes.
  345. return CSI.size() > 0 ? 2048 - getStackAlign().value()
  346. : (IsPrologue ? 2048 : 0);
  347. }
  348. return 0;
  349. }
  350. void LoongArchFrameLowering::determineCalleeSaves(MachineFunction &MF,
  351. BitVector &SavedRegs,
  352. RegScavenger *RS) const {
  353. TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
  354. // Unconditionally spill RA and FP only if the function uses a frame
  355. // pointer.
  356. if (hasFP(MF)) {
  357. SavedRegs.set(LoongArch::R1);
  358. SavedRegs.set(LoongArch::R22);
  359. }
  360. // Mark BP as used if function has dedicated base pointer.
  361. if (hasBP(MF))
  362. SavedRegs.set(LoongArchABI::getBPReg());
  363. }
  364. // Do not preserve stack space within prologue for outgoing variables if the
  365. // function contains variable size objects.
  366. // Let eliminateCallFramePseudoInstr preserve stack space for it.
  367. bool LoongArchFrameLowering::hasReservedCallFrame(
  368. const MachineFunction &MF) const {
  369. return !MF.getFrameInfo().hasVarSizedObjects();
  370. }
  371. // Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions.
  372. MachineBasicBlock::iterator
  373. LoongArchFrameLowering::eliminateCallFramePseudoInstr(
  374. MachineFunction &MF, MachineBasicBlock &MBB,
  375. MachineBasicBlock::iterator MI) const {
  376. Register SPReg = LoongArch::R3;
  377. DebugLoc DL = MI->getDebugLoc();
  378. if (!hasReservedCallFrame(MF)) {
  379. // If space has not been reserved for a call frame, ADJCALLSTACKDOWN and
  380. // ADJCALLSTACKUP must be converted to instructions manipulating the stack
  381. // pointer. This is necessary when there is a variable length stack
  382. // allocation (e.g. alloca), which means it's not possible to allocate
  383. // space for outgoing arguments from within the function prologue.
  384. int64_t Amount = MI->getOperand(0).getImm();
  385. if (Amount != 0) {
  386. // Ensure the stack remains aligned after adjustment.
  387. Amount = alignSPAdjust(Amount);
  388. if (MI->getOpcode() == LoongArch::ADJCALLSTACKDOWN)
  389. Amount = -Amount;
  390. adjustReg(MBB, MI, DL, SPReg, SPReg, Amount, MachineInstr::NoFlags);
  391. }
  392. }
  393. return MBB.erase(MI);
  394. }
  395. bool LoongArchFrameLowering::spillCalleeSavedRegisters(
  396. MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
  397. ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
  398. if (CSI.empty())
  399. return true;
  400. MachineFunction *MF = MBB.getParent();
  401. const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
  402. // Insert the spill to the stack frame.
  403. for (auto &CS : CSI) {
  404. Register Reg = CS.getReg();
  405. // If the register is RA and the return address is taken by method
  406. // LoongArchTargetLowering::lowerRETURNADDR, don't set kill flag.
  407. bool IsKill =
  408. !(Reg == LoongArch::R1 && MF->getFrameInfo().isReturnAddressTaken());
  409. const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
  410. TII.storeRegToStackSlot(MBB, MI, Reg, IsKill, CS.getFrameIdx(), RC, TRI,
  411. Register());
  412. }
  413. return true;
  414. }
  415. StackOffset LoongArchFrameLowering::getFrameIndexReference(
  416. const MachineFunction &MF, int FI, Register &FrameReg) const {
  417. const MachineFrameInfo &MFI = MF.getFrameInfo();
  418. const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();
  419. auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>();
  420. uint64_t StackSize = MFI.getStackSize();
  421. uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
  422. // Callee-saved registers should be referenced relative to the stack
  423. // pointer (positive offset), otherwise use the frame pointer (negative
  424. // offset).
  425. const auto &CSI = MFI.getCalleeSavedInfo();
  426. int MinCSFI = 0;
  427. int MaxCSFI = -1;
  428. StackOffset Offset =
  429. StackOffset::getFixed(MFI.getObjectOffset(FI) - getOffsetOfLocalArea() +
  430. MFI.getOffsetAdjustment());
  431. if (CSI.size()) {
  432. MinCSFI = CSI[0].getFrameIdx();
  433. MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
  434. }
  435. if (FI >= MinCSFI && FI <= MaxCSFI) {
  436. FrameReg = LoongArch::R3;
  437. if (FirstSPAdjustAmount)
  438. Offset += StackOffset::getFixed(FirstSPAdjustAmount);
  439. else
  440. Offset += StackOffset::getFixed(StackSize);
  441. } else if (RI->hasStackRealignment(MF) && !MFI.isFixedObjectIndex(FI)) {
  442. // If the stack was realigned, the frame pointer is set in order to allow
  443. // SP to be restored, so we need another base register to record the stack
  444. // after realignment.
  445. FrameReg = hasBP(MF) ? LoongArchABI::getBPReg() : LoongArch::R3;
  446. Offset += StackOffset::getFixed(StackSize);
  447. } else {
  448. FrameReg = RI->getFrameRegister(MF);
  449. if (hasFP(MF))
  450. Offset += StackOffset::getFixed(LoongArchFI->getVarArgsSaveSize());
  451. else
  452. Offset += StackOffset::getFixed(StackSize);
  453. }
  454. return Offset;
  455. }