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