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