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