1//===- MipsRegisterInfo.cpp - MIPS Register 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 MIPS implementation of the TargetRegisterInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MipsRegisterInfo.h"
14#include "MCTargetDesc/MipsABIInfo.h"
15#include "Mips.h"
16#include "MipsMachineFunction.h"
17#include "MipsSubtarget.h"
18#include "MipsTargetMachine.h"
19#include "llvm/ADT/BitVector.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstr.h"
23#include "llvm/CodeGen/MachineRegisterInfo.h"
24#include "llvm/CodeGen/TargetFrameLowering.h"
25#include "llvm/CodeGen/TargetRegisterInfo.h"
26#include "llvm/CodeGen/TargetSubtargetInfo.h"
27#include "llvm/IR/Function.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/ErrorHandling.h"
30#include "llvm/Support/raw_ostream.h"
31#include <cstdint>
32
33using namespace llvm;
34
35#define DEBUG_TYPE "mips-reg-info"
36
37#define GET_REGINFO_TARGET_DESC
38#include "MipsGenRegisterInfo.inc"
39
40MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &STI)
41 : MipsGenRegisterInfo(Mips::RA), ArePtrs64bit(STI.getABI().ArePtrs64bit()) {
42 MIPS_MC::initLLVMToCVRegMapping(MRI: this);
43}
44
45unsigned MipsRegisterInfo::getPICCallReg() { return Mips::T9; }
46
47const TargetRegisterClass *
48MipsRegisterInfo::getPointerRegClass(unsigned Kind) const {
49 assert(Kind == 0 && "this should only be used for default case");
50 return ArePtrs64bit ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
51}
52
53unsigned
54MipsRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
55 MachineFunction &MF) const {
56 switch (RC->getID()) {
57 default:
58 return 0;
59 case Mips::GPR32RegClassID:
60 case Mips::GPR64RegClassID:
61 case Mips::DSPRRegClassID: {
62 const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
63 return 28 - TFI->hasFP(MF);
64 }
65 case Mips::FGR32RegClassID:
66 return 32;
67 case Mips::AFGR64RegClassID:
68 return 16;
69 case Mips::FGR64RegClassID:
70 return 32;
71 }
72}
73
74//===----------------------------------------------------------------------===//
75// Callee Saved Registers methods
76//===----------------------------------------------------------------------===//
77
78/// Mips Callee Saved Registers
79const MCPhysReg *
80MipsRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
81 const MipsSubtarget &Subtarget = MF->getSubtarget<MipsSubtarget>();
82 const Function &F = MF->getFunction();
83 if (F.hasFnAttribute(Kind: "interrupt")) {
84 if (Subtarget.hasMips64())
85 return Subtarget.hasMips64r6() ? CSR_Interrupt_64R6_SaveList
86 : CSR_Interrupt_64_SaveList;
87 else
88 return Subtarget.hasMips32r6() ? CSR_Interrupt_32R6_SaveList
89 : CSR_Interrupt_32_SaveList;
90 }
91
92 // N64 ABI
93 if (Subtarget.isABI_N64()) {
94 if (Subtarget.isSingleFloat())
95 return CSR_N64_SingleFloat_SaveList;
96
97 return CSR_N64_SaveList;
98 }
99
100 // N32 ABI
101 if (Subtarget.isABI_N32()) {
102 if (Subtarget.isSingleFloat())
103 return CSR_N32_SingleFloat_SaveList;
104
105 return CSR_N32_SaveList;
106 }
107
108 // O32 ABI
109 if (Subtarget.isSingleFloat())
110 return CSR_O32_SingleFloat_SaveList;
111
112 if (Subtarget.isFP64bit())
113 return CSR_O32_FP64_SaveList;
114
115 if (Subtarget.isFPXX())
116 return CSR_O32_FPXX_SaveList;
117
118 return CSR_O32_SaveList;
119}
120
121const uint32_t *
122MipsRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
123 CallingConv::ID) const {
124 const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
125 // N64 ABI
126 if (Subtarget.isABI_N64()) {
127 if (Subtarget.isSingleFloat())
128 return CSR_N64_SingleFloat_RegMask;
129
130 return CSR_N64_RegMask;
131 }
132
133 // N32 ABI
134 if (Subtarget.isABI_N32()) {
135 if (Subtarget.isSingleFloat())
136 return CSR_N32_SingleFloat_RegMask;
137
138 return CSR_N32_RegMask;
139 }
140
141 // O32 ABI
142 if (Subtarget.isSingleFloat())
143 return CSR_O32_SingleFloat_RegMask;
144
145 if (Subtarget.isFP64bit())
146 return CSR_O32_FP64_RegMask;
147
148 if (Subtarget.isFPXX())
149 return CSR_O32_FPXX_RegMask;
150
151 return CSR_O32_RegMask;
152}
153
154const uint32_t *MipsRegisterInfo::getMips16RetHelperMask() {
155 return CSR_Mips16RetHelper_RegMask;
156}
157
158BitVector MipsRegisterInfo::
159getReservedRegs(const MachineFunction &MF) const {
160 static const MCPhysReg ReservedGPR32[] = {
161 Mips::ZERO, Mips::K0, Mips::K1, Mips::SP
162 };
163
164 static const MCPhysReg ReservedGPR64[] = {
165 Mips::ZERO_64, Mips::K0_64, Mips::K1_64, Mips::SP_64
166 };
167
168 BitVector Reserved(getNumRegs());
169 const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
170
171 for (MCPhysReg R : ReservedGPR32)
172 Reserved.set(R);
173
174 for (MCPhysReg R : ReservedGPR64)
175 Reserved.set(R);
176
177 // For mno-abicalls, GP is a program invariant!
178 if (!Subtarget.isABICalls()) {
179 Reserved.set(Mips::GP);
180 Reserved.set(Mips::GP_64);
181 }
182
183 if (Subtarget.isFP64bit()) {
184 // Reserve all registers in AFGR64.
185 for (MCPhysReg Reg : Mips::AFGR64RegClass)
186 Reserved.set(Reg);
187 } else {
188 // Reserve all registers in FGR64.
189 for (MCPhysReg Reg : Mips::FGR64RegClass)
190 Reserved.set(Reg);
191 }
192 // Reserve FP if this function should have a dedicated frame pointer register.
193 if (Subtarget.getFrameLowering()->hasFP(MF)) {
194 if (Subtarget.inMips16Mode())
195 Reserved.set(Mips::S0);
196 else {
197 Reserved.set(Mips::FP);
198 Reserved.set(Mips::FP_64);
199
200 // Reserve the base register if we need to both realign the stack and
201 // allocate variable-sized objects at runtime. This should test the
202 // same conditions as MipsFrameLowering::hasBP().
203 if (hasStackRealignment(MF) && MF.getFrameInfo().hasVarSizedObjects()) {
204 Reserved.set(Mips::S7);
205 Reserved.set(Mips::S7_64);
206 }
207 }
208 }
209 // Reserve fp control and status register
210 Reserved.set(Mips::FCR31);
211
212 // Reserve hardware registers.
213 Reserved.set(Mips::HWR29);
214 Reserved.set(Mips::HWR2);
215
216 // Reserve DSP control register.
217 Reserved.set(Mips::DSPPos);
218 Reserved.set(Mips::DSPSCount);
219 Reserved.set(Mips::DSPCarry);
220 Reserved.set(Mips::DSPEFI);
221 Reserved.set(Mips::DSPOutFlag);
222
223 // Reserve MSA control registers.
224 for (MCPhysReg Reg : Mips::MSACtrlRegClass)
225 Reserved.set(Reg);
226
227 // Reserve RA if in mips16 mode.
228 if (Subtarget.inMips16Mode()) {
229 const MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
230 Reserved.set(Mips::RA);
231 Reserved.set(Mips::RA_64);
232 Reserved.set(Mips::T0);
233 Reserved.set(Mips::T1);
234 if (MF.getFunction().hasFnAttribute(Kind: "saveS2") || MipsFI->hasSaveS2())
235 Reserved.set(Mips::S2);
236 }
237
238 // Reserve GP if small section is used.
239 if (Subtarget.useSmallSection()) {
240 Reserved.set(Mips::GP);
241 Reserved.set(Mips::GP_64);
242 }
243
244 return Reserved;
245}
246
247// FrameIndex represent objects inside a abstract stack.
248// We must replace FrameIndex with an stack/frame pointer
249// direct reference.
250bool MipsRegisterInfo::
251eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
252 unsigned FIOperandNum, RegScavenger *RS) const {
253 MachineInstr &MI = *II;
254 MachineFunction &MF = *MI.getParent()->getParent();
255
256 LLVM_DEBUG(errs() << "\nFunction : " << MF.getName() << "\n";
257 errs() << "<--------->\n"
258 << MI);
259
260 int FrameIndex = MI.getOperand(i: FIOperandNum).getIndex();
261 uint64_t stackSize = MF.getFrameInfo().getStackSize();
262 int64_t spOffset = MF.getFrameInfo().getObjectOffset(ObjectIdx: FrameIndex);
263
264 LLVM_DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n"
265 << "spOffset : " << spOffset << "\n"
266 << "stackSize : " << stackSize << "\n"
267 << "alignment : "
268 << DebugStr(MF.getFrameInfo().getObjectAlign(FrameIndex))
269 << "\n");
270
271 eliminateFI(II: MI, OpNo: FIOperandNum, FrameIndex, StackSize: stackSize, SPOffset: spOffset);
272 return false;
273}
274
275Register MipsRegisterInfo::
276getFrameRegister(const MachineFunction &MF) const {
277 const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
278 const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
279 bool IsN64 =
280 static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64();
281
282 if (Subtarget.inMips16Mode())
283 return TFI->hasFP(MF) ? Mips::S0 : Mips::SP;
284 else
285 return TFI->hasFP(MF) ? (IsN64 ? Mips::FP_64 : Mips::FP) :
286 (IsN64 ? Mips::SP_64 : Mips::SP);
287}
288
289bool MipsRegisterInfo::canRealignStack(const MachineFunction &MF) const {
290 // Avoid realigning functions that explicitly do not want to be realigned.
291 // Normally, we should report an error when a function should be dynamically
292 // realigned but also has the attribute no-realign-stack. Unfortunately,
293 // with this attribute, MachineFrameInfo clamps each new object's alignment
294 // to that of the stack's alignment as specified by the ABI. As a result,
295 // the information of whether we have objects with larger alignment
296 // requirement than the stack's alignment is already lost at this point.
297 if (!TargetRegisterInfo::canRealignStack(MF))
298 return false;
299
300 const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
301 unsigned FP = Subtarget.isGP32bit() ? Mips::FP : Mips::FP_64;
302 unsigned BP = Subtarget.isGP32bit() ? Mips::S7 : Mips::S7_64;
303
304 // Support dynamic stack realignment for all targets except Mips16.
305 if (Subtarget.inMips16Mode())
306 return false;
307
308 // We can't perform dynamic stack realignment if we can't reserve the
309 // frame pointer register.
310 if (!MF.getRegInfo().canReserveReg(PhysReg: FP))
311 return false;
312
313 // We can realign the stack if we know the maximum call frame size and we
314 // don't have variable sized objects.
315 if (Subtarget.getFrameLowering()->hasReservedCallFrame(MF))
316 return true;
317
318 // We have to reserve the base pointer register in the presence of variable
319 // sized objects.
320 return MF.getRegInfo().canReserveReg(PhysReg: BP);
321}
322