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/LoongArchBaseInfo.h"
19 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
20 #include "llvm/CodeGen/MachineFrameInfo.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/RegisterScavenging.h"
24 #include "llvm/CodeGen/TargetFrameLowering.h"
25 #include "llvm/CodeGen/TargetInstrInfo.h"
26 #include "llvm/Support/ErrorHandling.h"
30 #define GET_REGINFO_TARGET_DESC
31 #include "LoongArchGenRegisterInfo.inc"
33 LoongArchRegisterInfo::LoongArchRegisterInfo(unsigned HwMode
)
34 : LoongArchGenRegisterInfo(LoongArch::R1
, /*DwarfFlavour*/ 0,
39 LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction
*MF
) const {
40 auto &Subtarget
= MF
->getSubtarget
<LoongArchSubtarget
>();
42 if (MF
->getFunction().getCallingConv() == CallingConv::GHC
)
43 return CSR_NoRegs_SaveList
;
44 switch (Subtarget
.getTargetABI()) {
46 llvm_unreachable("Unrecognized ABI");
47 case LoongArchABI::ABI_ILP32S
:
48 case LoongArchABI::ABI_LP64S
:
49 return CSR_ILP32S_LP64S_SaveList
;
50 case LoongArchABI::ABI_ILP32F
:
51 case LoongArchABI::ABI_LP64F
:
52 return CSR_ILP32F_LP64F_SaveList
;
53 case LoongArchABI::ABI_ILP32D
:
54 case LoongArchABI::ABI_LP64D
:
55 return CSR_ILP32D_LP64D_SaveList
;
60 LoongArchRegisterInfo::getCallPreservedMask(const MachineFunction
&MF
,
61 CallingConv::ID CC
) const {
62 auto &Subtarget
= MF
.getSubtarget
<LoongArchSubtarget
>();
64 if (CC
== CallingConv::GHC
)
65 return CSR_NoRegs_RegMask
;
66 switch (Subtarget
.getTargetABI()) {
68 llvm_unreachable("Unrecognized ABI");
69 case LoongArchABI::ABI_ILP32S
:
70 case LoongArchABI::ABI_LP64S
:
71 return CSR_ILP32S_LP64S_RegMask
;
72 case LoongArchABI::ABI_ILP32F
:
73 case LoongArchABI::ABI_LP64F
:
74 return CSR_ILP32F_LP64F_RegMask
;
75 case LoongArchABI::ABI_ILP32D
:
76 case LoongArchABI::ABI_LP64D
:
77 return CSR_ILP32D_LP64D_RegMask
;
81 const uint32_t *LoongArchRegisterInfo::getNoPreservedMask() const {
82 return CSR_NoRegs_RegMask
;
86 LoongArchRegisterInfo::getReservedRegs(const MachineFunction
&MF
) const {
87 const LoongArchFrameLowering
*TFI
= getFrameLowering(MF
);
88 BitVector
Reserved(getNumRegs());
90 // Use markSuperRegs to ensure any register aliases are also reserved
91 markSuperRegs(Reserved
, LoongArch::R0
); // zero
92 markSuperRegs(Reserved
, LoongArch::R2
); // tp
93 markSuperRegs(Reserved
, LoongArch::R3
); // sp
94 markSuperRegs(Reserved
, LoongArch::R21
); // non-allocatable
96 markSuperRegs(Reserved
, LoongArch::R22
); // fp
97 // Reserve the base register if we need to realign the stack and allocate
98 // variable-sized objects at runtime.
100 markSuperRegs(Reserved
, LoongArchABI::getBPReg()); // bp
102 assert(checkAllSuperRegsMarked(Reserved
));
107 LoongArchRegisterInfo::getFrameRegister(const MachineFunction
&MF
) const {
108 const TargetFrameLowering
*TFI
= getFrameLowering(MF
);
109 return TFI
->hasFP(MF
) ? LoongArch::R22
: LoongArch::R3
;
112 bool LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II
,
114 unsigned FIOperandNum
,
115 RegScavenger
*RS
) const {
116 // TODO: this implementation is a temporary placeholder which does just
117 // enough to allow other aspects of code generation to be tested.
119 assert(SPAdj
== 0 && "Unexpected non-zero SPAdj value");
121 MachineInstr
&MI
= *II
;
122 assert(MI
.getOperand(FIOperandNum
+ 1).isImm() &&
123 "Unexpected FI-consuming insn");
125 MachineBasicBlock
&MBB
= *MI
.getParent();
126 MachineFunction
&MF
= *MI
.getParent()->getParent();
127 MachineRegisterInfo
&MRI
= MF
.getRegInfo();
128 const LoongArchSubtarget
&STI
= MF
.getSubtarget
<LoongArchSubtarget
>();
129 const LoongArchInstrInfo
*TII
= STI
.getInstrInfo();
130 const TargetFrameLowering
*TFI
= MF
.getSubtarget().getFrameLowering();
131 DebugLoc DL
= MI
.getDebugLoc();
132 bool IsLA64
= STI
.is64Bit();
133 unsigned MIOpc
= MI
.getOpcode();
135 int FrameIndex
= MI
.getOperand(FIOperandNum
).getIndex();
138 TFI
->getFrameIndexReference(MF
, FrameIndex
, FrameReg
) +
139 StackOffset::getFixed(MI
.getOperand(FIOperandNum
+ 1).getImm());
141 bool FrameRegIsKill
= false;
143 if (!isInt
<12>(Offset
.getFixed())) {
144 unsigned Addi
= IsLA64
? LoongArch::ADDI_D
: LoongArch::ADDI_W
;
145 unsigned Add
= IsLA64
? LoongArch::ADD_D
: LoongArch::ADD_W
;
147 // The offset won't fit in an immediate, so use a scratch register instead.
148 // Modify Offset and FrameReg appropriately.
149 Register ScratchReg
= MRI
.createVirtualRegister(&LoongArch::GPRRegClass
);
150 TII
->movImm(MBB
, II
, DL
, ScratchReg
, Offset
.getFixed());
152 BuildMI(MBB
, II
, DL
, TII
->get(Add
), MI
.getOperand(0).getReg())
154 .addReg(ScratchReg
, RegState::Kill
);
155 MI
.eraseFromParent();
158 BuildMI(MBB
, II
, DL
, TII
->get(Add
), ScratchReg
)
160 .addReg(ScratchReg
, RegState::Kill
);
161 Offset
= StackOffset::getFixed(0);
162 FrameReg
= ScratchReg
;
163 FrameRegIsKill
= true;
167 if (MIOpc
== LoongArch::PseudoST_CFR
) {
168 Register ScratchReg
= MRI
.createVirtualRegister(&LoongArch::GPRRegClass
);
169 BuildMI(MBB
, II
, DL
, TII
->get(LoongArch::MOVCF2GR
), ScratchReg
)
170 .add(MI
.getOperand(0));
171 BuildMI(MBB
, II
, DL
, TII
->get(IsLA64
? LoongArch::ST_D
: LoongArch::ST_W
))
172 .addReg(ScratchReg
, RegState::Kill
)
174 .addImm(Offset
.getFixed());
175 MI
.eraseFromParent();
180 if (MIOpc
== LoongArch::PseudoLD_CFR
) {
181 Register ScratchReg
= MRI
.createVirtualRegister(&LoongArch::GPRRegClass
);
182 BuildMI(MBB
, II
, DL
, TII
->get(IsLA64
? LoongArch::LD_D
: LoongArch::LD_W
),
185 .addImm(Offset
.getFixed());
186 BuildMI(MBB
, II
, DL
, TII
->get(LoongArch::MOVGR2CF
))
187 .add(MI
.getOperand(0))
188 .addReg(ScratchReg
, RegState::Kill
);
189 MI
.eraseFromParent();
193 MI
.getOperand(FIOperandNum
)
194 .ChangeToRegister(FrameReg
, false, false, FrameRegIsKill
);
195 MI
.getOperand(FIOperandNum
+ 1).ChangeToImmediate(Offset
.getFixed());
199 bool LoongArchRegisterInfo::canRealignStack(const MachineFunction
&MF
) const {
200 if (!TargetRegisterInfo::canRealignStack(MF
))
203 const MachineRegisterInfo
*MRI
= &MF
.getRegInfo();
204 const LoongArchFrameLowering
*TFI
= getFrameLowering(MF
);
206 // Stack realignment requires a frame pointer. If we already started
207 // register allocation with frame pointer elimination, it is too late now.
208 if (!MRI
->canReserveReg(LoongArch::R22
))
211 // We may also need a base pointer if there are dynamic allocas or stack
212 // pointer adjustments around calls.
213 if (TFI
->hasReservedCallFrame(MF
))
216 // A base pointer is required and allowed. Check that it isn't too late to
218 return MRI
->canReserveReg(LoongArchABI::getBPReg());