LoongArchRegisterInfo.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. //===- LoongArchRegisterInfo.cpp - LoongArch Register 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 the TargetRegisterInfo
  10. // class.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "LoongArchRegisterInfo.h"
  14. #include "LoongArch.h"
  15. #include "LoongArchInstrInfo.h"
  16. #include "LoongArchSubtarget.h"
  17. #include "MCTargetDesc/LoongArchMCTargetDesc.h"
  18. #include "llvm/CodeGen/MachineFrameInfo.h"
  19. #include "llvm/CodeGen/MachineFunction.h"
  20. #include "llvm/CodeGen/MachineInstrBuilder.h"
  21. #include "llvm/CodeGen/RegisterScavenging.h"
  22. #include "llvm/CodeGen/TargetFrameLowering.h"
  23. #include "llvm/CodeGen/TargetInstrInfo.h"
  24. #include "llvm/Support/ErrorHandling.h"
  25. using namespace llvm;
  26. #define GET_REGINFO_TARGET_DESC
  27. #include "LoongArchGenRegisterInfo.inc"
  28. LoongArchRegisterInfo::LoongArchRegisterInfo(unsigned HwMode)
  29. : LoongArchGenRegisterInfo(LoongArch::R1, /*DwarfFlavour*/ 0,
  30. /*EHFlavor*/ 0,
  31. /*PC*/ 0, HwMode) {}
  32. const MCPhysReg *
  33. LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
  34. auto &Subtarget = MF->getSubtarget<LoongArchSubtarget>();
  35. if (MF->getFunction().getCallingConv() == CallingConv::GHC)
  36. return CSR_NoRegs_SaveList;
  37. switch (Subtarget.getTargetABI()) {
  38. default:
  39. llvm_unreachable("Unrecognized ABI");
  40. case LoongArchABI::ABI_ILP32S:
  41. case LoongArchABI::ABI_LP64S:
  42. return CSR_ILP32S_LP64S_SaveList;
  43. case LoongArchABI::ABI_ILP32F:
  44. case LoongArchABI::ABI_LP64F:
  45. return CSR_ILP32F_LP64F_SaveList;
  46. case LoongArchABI::ABI_ILP32D:
  47. case LoongArchABI::ABI_LP64D:
  48. return CSR_ILP32D_LP64D_SaveList;
  49. }
  50. }
  51. const uint32_t *
  52. LoongArchRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
  53. CallingConv::ID CC) const {
  54. auto &Subtarget = MF.getSubtarget<LoongArchSubtarget>();
  55. if (CC == CallingConv::GHC)
  56. return CSR_NoRegs_RegMask;
  57. switch (Subtarget.getTargetABI()) {
  58. default:
  59. llvm_unreachable("Unrecognized ABI");
  60. case LoongArchABI::ABI_ILP32S:
  61. case LoongArchABI::ABI_LP64S:
  62. return CSR_ILP32S_LP64S_RegMask;
  63. case LoongArchABI::ABI_ILP32F:
  64. case LoongArchABI::ABI_LP64F:
  65. return CSR_ILP32F_LP64F_RegMask;
  66. case LoongArchABI::ABI_ILP32D:
  67. case LoongArchABI::ABI_LP64D:
  68. return CSR_ILP32D_LP64D_RegMask;
  69. }
  70. }
  71. const uint32_t *LoongArchRegisterInfo::getNoPreservedMask() const {
  72. return CSR_NoRegs_RegMask;
  73. }
  74. BitVector
  75. LoongArchRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
  76. const LoongArchFrameLowering *TFI = getFrameLowering(MF);
  77. BitVector Reserved(getNumRegs());
  78. // Use markSuperRegs to ensure any register aliases are also reserved
  79. markSuperRegs(Reserved, LoongArch::R0); // zero
  80. markSuperRegs(Reserved, LoongArch::R2); // tp
  81. markSuperRegs(Reserved, LoongArch::R3); // sp
  82. markSuperRegs(Reserved, LoongArch::R21); // non-allocatable
  83. if (TFI->hasFP(MF))
  84. markSuperRegs(Reserved, LoongArch::R22); // fp
  85. // Reserve the base register if we need to realign the stack and allocate
  86. // variable-sized objects at runtime.
  87. if (TFI->hasBP(MF))
  88. markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp
  89. // FIXME: To avoid generating COPY instructions between CFRs, only use $fcc0.
  90. // This is required to work around the fact that COPY instruction between CFRs
  91. // is not provided in LoongArch.
  92. if (MF.getSubtarget<LoongArchSubtarget>().hasBasicF())
  93. for (size_t Reg = LoongArch::FCC1; Reg <= LoongArch::FCC7; ++Reg)
  94. markSuperRegs(Reserved, Reg);
  95. assert(checkAllSuperRegsMarked(Reserved));
  96. return Reserved;
  97. }
  98. Register
  99. LoongArchRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
  100. const TargetFrameLowering *TFI = getFrameLowering(MF);
  101. return TFI->hasFP(MF) ? LoongArch::R22 : LoongArch::R3;
  102. }
  103. bool LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
  104. int SPAdj,
  105. unsigned FIOperandNum,
  106. RegScavenger *RS) const {
  107. // TODO: this implementation is a temporary placeholder which does just
  108. // enough to allow other aspects of code generation to be tested.
  109. assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");
  110. MachineInstr &MI = *II;
  111. assert(MI.getOperand(FIOperandNum + 1).isImm() &&
  112. "Unexpected FI-consuming insn");
  113. MachineBasicBlock &MBB = *MI.getParent();
  114. MachineFunction &MF = *MI.getParent()->getParent();
  115. MachineRegisterInfo &MRI = MF.getRegInfo();
  116. const LoongArchSubtarget &STI = MF.getSubtarget<LoongArchSubtarget>();
  117. const LoongArchInstrInfo *TII = STI.getInstrInfo();
  118. const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
  119. DebugLoc DL = MI.getDebugLoc();
  120. bool IsLA64 = STI.is64Bit();
  121. unsigned MIOpc = MI.getOpcode();
  122. int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
  123. Register FrameReg;
  124. StackOffset Offset =
  125. TFI->getFrameIndexReference(MF, FrameIndex, FrameReg) +
  126. StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm());
  127. bool FrameRegIsKill = false;
  128. if (!isInt<12>(Offset.getFixed())) {
  129. unsigned Addi = IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W;
  130. unsigned Add = IsLA64 ? LoongArch::ADD_D : LoongArch::ADD_W;
  131. // The offset won't fit in an immediate, so use a scratch register instead.
  132. // Modify Offset and FrameReg appropriately.
  133. Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
  134. TII->movImm(MBB, II, DL, ScratchReg, Offset.getFixed());
  135. if (MIOpc == Addi) {
  136. BuildMI(MBB, II, DL, TII->get(Add), MI.getOperand(0).getReg())
  137. .addReg(FrameReg)
  138. .addReg(ScratchReg, RegState::Kill);
  139. MI.eraseFromParent();
  140. return true;
  141. }
  142. BuildMI(MBB, II, DL, TII->get(Add), ScratchReg)
  143. .addReg(FrameReg)
  144. .addReg(ScratchReg, RegState::Kill);
  145. Offset = StackOffset::getFixed(0);
  146. FrameReg = ScratchReg;
  147. FrameRegIsKill = true;
  148. }
  149. // Spill CFRs.
  150. if (MIOpc == LoongArch::PseudoST_CFR) {
  151. Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
  152. BuildMI(MBB, II, DL, TII->get(LoongArch::MOVCF2GR), ScratchReg)
  153. .add(MI.getOperand(0));
  154. BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
  155. .addReg(ScratchReg, RegState::Kill)
  156. .addReg(FrameReg)
  157. .addImm(Offset.getFixed());
  158. MI.eraseFromParent();
  159. return true;
  160. }
  161. // Reload CFRs.
  162. if (MIOpc == LoongArch::PseudoLD_CFR) {
  163. Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
  164. BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::LD_D : LoongArch::LD_W),
  165. ScratchReg)
  166. .addReg(FrameReg)
  167. .addImm(Offset.getFixed());
  168. BuildMI(MBB, II, DL, TII->get(LoongArch::MOVGR2CF))
  169. .add(MI.getOperand(0))
  170. .addReg(ScratchReg, RegState::Kill);
  171. MI.eraseFromParent();
  172. return true;
  173. }
  174. MI.getOperand(FIOperandNum)
  175. .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);
  176. MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed());
  177. return false;
  178. }