1 | //===- MipsSEFrameLowering.cpp - Mips32/64 Frame 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 Mips32/64 implementation of TargetFrameLowering class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "MipsSEFrameLowering.h" |
14 | #include "MCTargetDesc/MipsABIInfo.h" |
15 | #include "MipsMachineFunction.h" |
16 | #include "MipsRegisterInfo.h" |
17 | #include "MipsSEInstrInfo.h" |
18 | #include "MipsSubtarget.h" |
19 | #include "llvm/ADT/BitVector.h" |
20 | #include "llvm/ADT/StringRef.h" |
21 | #include "llvm/ADT/StringSwitch.h" |
22 | #include "llvm/CodeGen/CFIInstBuilder.h" |
23 | #include "llvm/CodeGen/MachineBasicBlock.h" |
24 | #include "llvm/CodeGen/MachineFrameInfo.h" |
25 | #include "llvm/CodeGen/MachineFunction.h" |
26 | #include "llvm/CodeGen/MachineInstr.h" |
27 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
28 | #include "llvm/CodeGen/MachineModuleInfo.h" |
29 | #include "llvm/CodeGen/MachineOperand.h" |
30 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
31 | #include "llvm/CodeGen/RegisterScavenging.h" |
32 | #include "llvm/CodeGen/TargetInstrInfo.h" |
33 | #include "llvm/CodeGen/TargetRegisterInfo.h" |
34 | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
35 | #include "llvm/IR/DebugLoc.h" |
36 | #include "llvm/IR/Function.h" |
37 | #include "llvm/Support/CodeGen.h" |
38 | #include "llvm/Support/ErrorHandling.h" |
39 | #include "llvm/Support/MathExtras.h" |
40 | #include <cassert> |
41 | #include <cstdint> |
42 | #include <utility> |
43 | #include <vector> |
44 | |
45 | using namespace llvm; |
46 | |
47 | static std::pair<unsigned, unsigned> getMFHiLoOpc(unsigned Src) { |
48 | if (Mips::ACC64RegClass.contains(Reg: Src)) |
49 | return std::make_pair(x: (unsigned)Mips::PseudoMFHI, |
50 | y: (unsigned)Mips::PseudoMFLO); |
51 | |
52 | if (Mips::ACC64DSPRegClass.contains(Reg: Src)) |
53 | return std::make_pair(x: (unsigned)Mips::MFHI_DSP, y: (unsigned)Mips::MFLO_DSP); |
54 | |
55 | if (Mips::ACC128RegClass.contains(Reg: Src)) |
56 | return std::make_pair(x: (unsigned)Mips::PseudoMFHI64, |
57 | y: (unsigned)Mips::PseudoMFLO64); |
58 | |
59 | return std::make_pair(x: 0, y: 0); |
60 | } |
61 | |
62 | namespace { |
63 | |
64 | /// Helper class to expand pseudos. |
65 | class ExpandPseudo { |
66 | public: |
67 | ExpandPseudo(MachineFunction &MF); |
68 | bool expand(); |
69 | |
70 | private: |
71 | using Iter = MachineBasicBlock::iterator; |
72 | |
73 | bool expandInstr(MachineBasicBlock &MBB, Iter I); |
74 | void expandLoadCCond(MachineBasicBlock &MBB, Iter I); |
75 | void expandStoreCCond(MachineBasicBlock &MBB, Iter I); |
76 | void expandLoadACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize); |
77 | void expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc, |
78 | unsigned MFLoOpc, unsigned RegSize); |
79 | bool expandCopy(MachineBasicBlock &MBB, Iter I); |
80 | bool expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc, |
81 | unsigned MFLoOpc); |
82 | bool expandBuildPairF64(MachineBasicBlock &MBB, |
83 | MachineBasicBlock::iterator I, bool FP64) const; |
84 | bool expandExtractElementF64(MachineBasicBlock &MBB, |
85 | MachineBasicBlock::iterator I, bool FP64) const; |
86 | |
87 | MachineFunction &MF; |
88 | MachineRegisterInfo &MRI; |
89 | const MipsSubtarget &Subtarget; |
90 | const MipsSEInstrInfo &TII; |
91 | const MipsRegisterInfo &RegInfo; |
92 | }; |
93 | |
94 | } // end anonymous namespace |
95 | |
96 | ExpandPseudo::ExpandPseudo(MachineFunction &MF_) |
97 | : MF(MF_), MRI(MF.getRegInfo()), |
98 | Subtarget(MF.getSubtarget<MipsSubtarget>()), |
99 | TII(*static_cast<const MipsSEInstrInfo *>(Subtarget.getInstrInfo())), |
100 | RegInfo(*Subtarget.getRegisterInfo()) {} |
101 | |
102 | bool ExpandPseudo::expand() { |
103 | bool Expanded = false; |
104 | |
105 | for (auto &MBB : MF) { |
106 | for (Iter I = MBB.begin(), End = MBB.end(); I != End;) |
107 | Expanded |= expandInstr(MBB, I: I++); |
108 | } |
109 | |
110 | return Expanded; |
111 | } |
112 | |
113 | bool ExpandPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) { |
114 | switch(I->getOpcode()) { |
115 | case Mips::LOAD_CCOND_DSP: |
116 | expandLoadCCond(MBB, I); |
117 | break; |
118 | case Mips::STORE_CCOND_DSP: |
119 | expandStoreCCond(MBB, I); |
120 | break; |
121 | case Mips::LOAD_ACC64: |
122 | case Mips::LOAD_ACC64DSP: |
123 | expandLoadACC(MBB, I, RegSize: 4); |
124 | break; |
125 | case Mips::LOAD_ACC128: |
126 | expandLoadACC(MBB, I, RegSize: 8); |
127 | break; |
128 | case Mips::STORE_ACC64: |
129 | expandStoreACC(MBB, I, MFHiOpc: Mips::PseudoMFHI, MFLoOpc: Mips::PseudoMFLO, RegSize: 4); |
130 | break; |
131 | case Mips::STORE_ACC64DSP: |
132 | expandStoreACC(MBB, I, MFHiOpc: Mips::MFHI_DSP, MFLoOpc: Mips::MFLO_DSP, RegSize: 4); |
133 | break; |
134 | case Mips::STORE_ACC128: |
135 | expandStoreACC(MBB, I, MFHiOpc: Mips::PseudoMFHI64, MFLoOpc: Mips::PseudoMFLO64, RegSize: 8); |
136 | break; |
137 | case Mips::BuildPairF64: |
138 | if (expandBuildPairF64(MBB, I, FP64: false)) |
139 | MBB.erase(I); |
140 | return false; |
141 | case Mips::BuildPairF64_64: |
142 | if (expandBuildPairF64(MBB, I, FP64: true)) |
143 | MBB.erase(I); |
144 | return false; |
145 | case Mips::ExtractElementF64: |
146 | if (expandExtractElementF64(MBB, I, FP64: false)) |
147 | MBB.erase(I); |
148 | return false; |
149 | case Mips::ExtractElementF64_64: |
150 | if (expandExtractElementF64(MBB, I, FP64: true)) |
151 | MBB.erase(I); |
152 | return false; |
153 | case TargetOpcode::COPY: |
154 | if (!expandCopy(MBB, I)) |
155 | return false; |
156 | break; |
157 | default: |
158 | return false; |
159 | } |
160 | |
161 | MBB.erase(I); |
162 | return true; |
163 | } |
164 | |
165 | void ExpandPseudo::expandLoadCCond(MachineBasicBlock &MBB, Iter I) { |
166 | // load $vr, FI |
167 | // copy ccond, $vr |
168 | |
169 | assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); |
170 | |
171 | const TargetRegisterClass *RC = RegInfo.intRegClass(Size: 4); |
172 | Register VR = MRI.createVirtualRegister(RegClass: RC); |
173 | Register Dst = I->getOperand(i: 0).getReg(), FI = I->getOperand(i: 1).getIndex(); |
174 | |
175 | TII.loadRegFromStack(MBB, MI: I, DestReg: VR, FrameIndex: FI, RC, TRI: &RegInfo, Offset: 0); |
176 | BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: TII.get(Opcode: TargetOpcode::COPY), DestReg: Dst) |
177 | .addReg(RegNo: VR, flags: RegState::Kill); |
178 | } |
179 | |
180 | void ExpandPseudo::expandStoreCCond(MachineBasicBlock &MBB, Iter I) { |
181 | // copy $vr, ccond |
182 | // store $vr, FI |
183 | |
184 | assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); |
185 | |
186 | const TargetRegisterClass *RC = RegInfo.intRegClass(Size: 4); |
187 | Register VR = MRI.createVirtualRegister(RegClass: RC); |
188 | Register Src = I->getOperand(i: 0).getReg(), FI = I->getOperand(i: 1).getIndex(); |
189 | |
190 | BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: TII.get(Opcode: TargetOpcode::COPY), DestReg: VR) |
191 | .addReg(RegNo: Src, flags: getKillRegState(B: I->getOperand(i: 0).isKill())); |
192 | TII.storeRegToStack(MBB, MI: I, SrcReg: VR, isKill: true, FrameIndex: FI, RC, TRI: &RegInfo, Offset: 0); |
193 | } |
194 | |
195 | void ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I, |
196 | unsigned RegSize) { |
197 | // load $vr0, FI |
198 | // copy lo, $vr0 |
199 | // load $vr1, FI + 4 |
200 | // copy hi, $vr1 |
201 | |
202 | assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); |
203 | |
204 | const TargetRegisterClass *RC = RegInfo.intRegClass(Size: RegSize); |
205 | Register VR0 = MRI.createVirtualRegister(RegClass: RC); |
206 | Register VR1 = MRI.createVirtualRegister(RegClass: RC); |
207 | Register Dst = I->getOperand(i: 0).getReg(), FI = I->getOperand(i: 1).getIndex(); |
208 | Register Lo = RegInfo.getSubReg(Reg: Dst, Idx: Mips::sub_lo); |
209 | Register Hi = RegInfo.getSubReg(Reg: Dst, Idx: Mips::sub_hi); |
210 | DebugLoc DL = I->getDebugLoc(); |
211 | const MCInstrDesc &Desc = TII.get(Opcode: TargetOpcode::COPY); |
212 | |
213 | TII.loadRegFromStack(MBB, MI: I, DestReg: VR0, FrameIndex: FI, RC, TRI: &RegInfo, Offset: 0); |
214 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: Desc, DestReg: Lo).addReg(RegNo: VR0, flags: RegState::Kill); |
215 | TII.loadRegFromStack(MBB, MI: I, DestReg: VR1, FrameIndex: FI, RC, TRI: &RegInfo, Offset: RegSize); |
216 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: Desc, DestReg: Hi).addReg(RegNo: VR1, flags: RegState::Kill); |
217 | } |
218 | |
219 | void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I, |
220 | unsigned MFHiOpc, unsigned MFLoOpc, |
221 | unsigned RegSize) { |
222 | // mflo $vr0, src |
223 | // store $vr0, FI |
224 | // mfhi $vr1, src |
225 | // store $vr1, FI + 4 |
226 | |
227 | assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); |
228 | |
229 | const TargetRegisterClass *RC = RegInfo.intRegClass(Size: RegSize); |
230 | Register VR0 = MRI.createVirtualRegister(RegClass: RC); |
231 | Register VR1 = MRI.createVirtualRegister(RegClass: RC); |
232 | Register Src = I->getOperand(i: 0).getReg(), FI = I->getOperand(i: 1).getIndex(); |
233 | unsigned SrcKill = getKillRegState(B: I->getOperand(i: 0).isKill()); |
234 | DebugLoc DL = I->getDebugLoc(); |
235 | |
236 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: MFLoOpc), DestReg: VR0).addReg(RegNo: Src); |
237 | TII.storeRegToStack(MBB, MI: I, SrcReg: VR0, isKill: true, FrameIndex: FI, RC, TRI: &RegInfo, Offset: 0); |
238 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: MFHiOpc), DestReg: VR1).addReg(RegNo: Src, flags: SrcKill); |
239 | TII.storeRegToStack(MBB, MI: I, SrcReg: VR1, isKill: true, FrameIndex: FI, RC, TRI: &RegInfo, Offset: RegSize); |
240 | } |
241 | |
242 | bool ExpandPseudo::expandCopy(MachineBasicBlock &MBB, Iter I) { |
243 | Register Src = I->getOperand(i: 1).getReg(); |
244 | std::pair<unsigned, unsigned> Opcodes = getMFHiLoOpc(Src); |
245 | |
246 | if (!Opcodes.first) |
247 | return false; |
248 | |
249 | return expandCopyACC(MBB, I, MFHiOpc: Opcodes.first, MFLoOpc: Opcodes.second); |
250 | } |
251 | |
252 | bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, |
253 | unsigned MFHiOpc, unsigned MFLoOpc) { |
254 | // mflo $vr0, src |
255 | // copy dst_lo, $vr0 |
256 | // mfhi $vr1, src |
257 | // copy dst_hi, $vr1 |
258 | |
259 | unsigned Dst = I->getOperand(i: 0).getReg(), Src = I->getOperand(i: 1).getReg(); |
260 | const TargetRegisterClass *DstRC = RegInfo.getMinimalPhysRegClass(Reg: Dst); |
261 | unsigned VRegSize = RegInfo.getRegSizeInBits(RC: *DstRC) / 16; |
262 | const TargetRegisterClass *RC = RegInfo.intRegClass(Size: VRegSize); |
263 | Register VR0 = MRI.createVirtualRegister(RegClass: RC); |
264 | Register VR1 = MRI.createVirtualRegister(RegClass: RC); |
265 | unsigned SrcKill = getKillRegState(B: I->getOperand(i: 1).isKill()); |
266 | Register DstLo = RegInfo.getSubReg(Reg: Dst, Idx: Mips::sub_lo); |
267 | Register DstHi = RegInfo.getSubReg(Reg: Dst, Idx: Mips::sub_hi); |
268 | DebugLoc DL = I->getDebugLoc(); |
269 | |
270 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: MFLoOpc), DestReg: VR0).addReg(RegNo: Src); |
271 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: TargetOpcode::COPY), DestReg: DstLo) |
272 | .addReg(RegNo: VR0, flags: RegState::Kill); |
273 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: MFHiOpc), DestReg: VR1).addReg(RegNo: Src, flags: SrcKill); |
274 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: TargetOpcode::COPY), DestReg: DstHi) |
275 | .addReg(RegNo: VR1, flags: RegState::Kill); |
276 | return true; |
277 | } |
278 | |
279 | /// This method expands the same instruction that MipsSEInstrInfo:: |
280 | /// expandBuildPairF64 does, for the case when ABI is fpxx and mthc1 is not |
281 | /// available and the case where the ABI is FP64A. It is implemented here |
282 | /// because frame indexes are eliminated before MipsSEInstrInfo:: |
283 | /// expandBuildPairF64 is called. |
284 | bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB, |
285 | MachineBasicBlock::iterator I, |
286 | bool FP64) const { |
287 | // For fpxx and when mthc1 is not available, use: |
288 | // spill + reload via ldc1 |
289 | // |
290 | // The case where dmtc1 is available doesn't need to be handled here |
291 | // because it never creates a BuildPairF64 node. |
292 | // |
293 | // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence |
294 | // for odd-numbered double precision values (because the lower 32-bits is |
295 | // transferred with mtc1 which is redirected to the upper half of the even |
296 | // register). Unfortunately, we have to make this decision before register |
297 | // allocation so for now we use a spill/reload sequence for all |
298 | // double-precision values in regardless of being an odd/even register. |
299 | // |
300 | // For the cases that should be covered here MipsSEISelDAGToDAG adds $sp as |
301 | // implicit operand, so other passes (like ShrinkWrapping) are aware that |
302 | // stack is used. |
303 | if (I->getNumOperands() == 4 && I->getOperand(i: 3).isReg() |
304 | && I->getOperand(i: 3).getReg() == Mips::SP) { |
305 | Register DstReg = I->getOperand(i: 0).getReg(); |
306 | Register LoReg = I->getOperand(i: 1).getReg(); |
307 | Register HiReg = I->getOperand(i: 2).getReg(); |
308 | |
309 | // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are |
310 | // the cases where mthc1 is not available). 64-bit architectures and |
311 | // MIPS32r2 or later can use FGR64 though. |
312 | assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() || |
313 | !Subtarget.isFP64bit()); |
314 | |
315 | const TargetRegisterClass *RC = &Mips::GPR32RegClass; |
316 | const TargetRegisterClass *RC2 = |
317 | FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; |
318 | |
319 | // We re-use the same spill slot each time so that the stack frame doesn't |
320 | // grow too much in functions with a large number of moves. |
321 | int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(MF, RC: RC2); |
322 | if (!Subtarget.isLittle()) |
323 | std::swap(a&: LoReg, b&: HiReg); |
324 | TII.storeRegToStack(MBB, MI: I, SrcReg: LoReg, isKill: I->getOperand(i: 1).isKill(), FrameIndex: FI, RC, |
325 | TRI: &RegInfo, Offset: 0); |
326 | TII.storeRegToStack(MBB, MI: I, SrcReg: HiReg, isKill: I->getOperand(i: 2).isKill(), FrameIndex: FI, RC, |
327 | TRI: &RegInfo, Offset: 4); |
328 | TII.loadRegFromStack(MBB, MI: I, DestReg: DstReg, FrameIndex: FI, RC: RC2, TRI: &RegInfo, Offset: 0); |
329 | return true; |
330 | } |
331 | |
332 | return false; |
333 | } |
334 | |
335 | /// This method expands the same instruction that MipsSEInstrInfo:: |
336 | /// expandExtractElementF64 does, for the case when ABI is fpxx and mfhc1 is not |
337 | /// available and the case where the ABI is FP64A. It is implemented here |
338 | /// because frame indexes are eliminated before MipsSEInstrInfo:: |
339 | /// expandExtractElementF64 is called. |
340 | bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB, |
341 | MachineBasicBlock::iterator I, |
342 | bool FP64) const { |
343 | const MachineOperand &Op1 = I->getOperand(i: 1); |
344 | const MachineOperand &Op2 = I->getOperand(i: 2); |
345 | |
346 | if ((Op1.isReg() && Op1.isUndef()) || (Op2.isReg() && Op2.isUndef())) { |
347 | Register DstReg = I->getOperand(i: 0).getReg(); |
348 | BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: TII.get(Opcode: Mips::IMPLICIT_DEF), DestReg: DstReg); |
349 | return true; |
350 | } |
351 | |
352 | // For fpxx and when mfhc1 is not available, use: |
353 | // spill + reload via ldc1 |
354 | // |
355 | // The case where dmfc1 is available doesn't need to be handled here |
356 | // because it never creates a ExtractElementF64 node. |
357 | // |
358 | // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence |
359 | // for odd-numbered double precision values (because the lower 32-bits is |
360 | // transferred with mfc1 which is redirected to the upper half of the even |
361 | // register). Unfortunately, we have to make this decision before register |
362 | // allocation so for now we use a spill/reload sequence for all |
363 | // double-precision values in regardless of being an odd/even register. |
364 | // |
365 | // For the cases that should be covered here MipsSEISelDAGToDAG adds $sp as |
366 | // implicit operand, so other passes (like ShrinkWrapping) are aware that |
367 | // stack is used. |
368 | if (I->getNumOperands() == 4 && I->getOperand(i: 3).isReg() |
369 | && I->getOperand(i: 3).getReg() == Mips::SP) { |
370 | Register DstReg = I->getOperand(i: 0).getReg(); |
371 | Register SrcReg = Op1.getReg(); |
372 | unsigned N = Op2.getImm(); |
373 | int64_t Offset = 4 * (Subtarget.isLittle() ? N : (1 - N)); |
374 | |
375 | // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are |
376 | // the cases where mfhc1 is not available). 64-bit architectures and |
377 | // MIPS32r2 or later can use FGR64 though. |
378 | assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() || |
379 | !Subtarget.isFP64bit()); |
380 | |
381 | const TargetRegisterClass *RC = |
382 | FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; |
383 | const TargetRegisterClass *RC2 = &Mips::GPR32RegClass; |
384 | |
385 | // We re-use the same spill slot each time so that the stack frame doesn't |
386 | // grow too much in functions with a large number of moves. |
387 | int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(MF, RC); |
388 | TII.storeRegToStack(MBB, MI: I, SrcReg, isKill: Op1.isKill(), FrameIndex: FI, RC, TRI: &RegInfo, Offset: 0); |
389 | TII.loadRegFromStack(MBB, MI: I, DestReg: DstReg, FrameIndex: FI, RC: RC2, TRI: &RegInfo, Offset); |
390 | return true; |
391 | } |
392 | |
393 | return false; |
394 | } |
395 | |
396 | MipsSEFrameLowering::MipsSEFrameLowering(const MipsSubtarget &STI) |
397 | : MipsFrameLowering(STI, STI.getStackAlignment()) {} |
398 | |
399 | void MipsSEFrameLowering::emitPrologue(MachineFunction &MF, |
400 | MachineBasicBlock &MBB) const { |
401 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
402 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); |
403 | |
404 | const MipsSEInstrInfo &TII = |
405 | *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo()); |
406 | const MipsRegisterInfo &RegInfo = |
407 | *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo()); |
408 | |
409 | MachineBasicBlock::iterator MBBI = MBB.begin(); |
410 | DebugLoc dl; |
411 | MipsABIInfo ABI = STI.getABI(); |
412 | unsigned SP = ABI.GetStackPtr(); |
413 | unsigned FP = ABI.GetFramePtr(); |
414 | unsigned ZERO = ABI.GetNullPtr(); |
415 | unsigned MOVE = ABI.GetGPRMoveOp(); |
416 | unsigned ADDiu = ABI.GetPtrAddiuOp(); |
417 | unsigned AND = ABI.IsN64() ? Mips::AND64 : Mips::AND; |
418 | |
419 | const TargetRegisterClass *RC = ABI.ArePtrs64bit() ? |
420 | &Mips::GPR64RegClass : &Mips::GPR32RegClass; |
421 | |
422 | // First, compute final stack size. |
423 | uint64_t StackSize = MFI.getStackSize(); |
424 | |
425 | // No need to allocate space on the stack. |
426 | if (StackSize == 0 && !MFI.adjustsStack()) return; |
427 | |
428 | CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::NoFlags); |
429 | |
430 | // Adjust stack. |
431 | TII.adjustStackPtr(SP, Amount: -StackSize, MBB, I: MBBI); |
432 | CFIBuilder.buildDefCFAOffset(Offset: StackSize); |
433 | |
434 | if (MF.getFunction().hasFnAttribute(Kind: "interrupt" )) |
435 | emitInterruptPrologueStub(MF, MBB); |
436 | |
437 | const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); |
438 | |
439 | // Find the instruction past the last instruction that saves a callee-saved |
440 | // register to the stack. |
441 | std::advance(i&: MBBI, n: CSI.size()); |
442 | CFIBuilder.setInsertPoint(MBBI); |
443 | |
444 | if (!CSI.empty()) { |
445 | // Iterate over list of callee-saved registers and emit .cfi_offset |
446 | // directives. |
447 | for (const CalleeSavedInfo &I : CSI) { |
448 | int64_t Offset = MFI.getObjectOffset(ObjectIdx: I.getFrameIdx()); |
449 | MCRegister Reg = I.getReg(); |
450 | |
451 | // If Reg is a double precision register, emit two cfa_offsets, |
452 | // one for each of the paired single precision registers. |
453 | if (Mips::AFGR64RegClass.contains(Reg)) { |
454 | MCRegister Reg0 = RegInfo.getSubReg(Reg, Idx: Mips::sub_lo); |
455 | MCRegister Reg1 = RegInfo.getSubReg(Reg, Idx: Mips::sub_hi); |
456 | |
457 | if (!STI.isLittle()) |
458 | std::swap(a&: Reg0, b&: Reg1); |
459 | |
460 | CFIBuilder.buildOffset(Reg: Reg0, Offset); |
461 | CFIBuilder.buildOffset(Reg: Reg1, Offset: Offset + 4); |
462 | } else if (Mips::FGR64RegClass.contains(Reg)) { |
463 | MCRegister Reg0 = Reg; |
464 | MCRegister Reg1 = Reg + 1; |
465 | |
466 | if (!STI.isLittle()) |
467 | std::swap(a&: Reg0, b&: Reg1); |
468 | |
469 | CFIBuilder.buildOffset(Reg: Reg0, Offset); |
470 | CFIBuilder.buildOffset(Reg: Reg1, Offset: Offset + 4); |
471 | } else { |
472 | // Reg is either in GPR32 or FGR32. |
473 | CFIBuilder.buildOffset(Reg, Offset); |
474 | } |
475 | } |
476 | } |
477 | |
478 | if (MipsFI->callsEhReturn()) { |
479 | // Insert instructions that spill eh data registers. |
480 | for (int I = 0; I < 4; ++I) { |
481 | if (!MBB.isLiveIn(Reg: ABI.GetEhDataReg(I))) |
482 | MBB.addLiveIn(PhysReg: ABI.GetEhDataReg(I)); |
483 | TII.storeRegToStackSlot(MBB, MBBI, SrcReg: ABI.GetEhDataReg(I), isKill: false, |
484 | FrameIndex: MipsFI->getEhDataRegFI(Reg: I), RC, TRI: &RegInfo, |
485 | VReg: Register()); |
486 | } |
487 | |
488 | // Emit .cfi_offset directives for eh data registers. |
489 | for (int I = 0; I < 4; ++I) { |
490 | int64_t Offset = MFI.getObjectOffset(ObjectIdx: MipsFI->getEhDataRegFI(Reg: I)); |
491 | CFIBuilder.buildOffset(Reg: ABI.GetEhDataReg(I), Offset); |
492 | } |
493 | } |
494 | |
495 | // if framepointer enabled, set it to point to the stack pointer. |
496 | if (hasFP(MF)) { |
497 | // Insert instruction "move $fp, $sp" at this location. |
498 | BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: MOVE), DestReg: FP).addReg(RegNo: SP).addReg(RegNo: ZERO) |
499 | .setMIFlag(MachineInstr::FrameSetup); |
500 | |
501 | CFIBuilder.buildDefCFARegister(Reg: FP); |
502 | |
503 | if (RegInfo.hasStackRealignment(MF)) { |
504 | // addiu $Reg, $zero, -MaxAlignment |
505 | // andi $sp, $sp, $Reg |
506 | Register VR = MF.getRegInfo().createVirtualRegister(RegClass: RC); |
507 | assert((Log2(MFI.getMaxAlign()) < 16) && |
508 | "Function's alignment size requirement is not supported." ); |
509 | int64_t MaxAlign = -(int64_t)MFI.getMaxAlign().value(); |
510 | |
511 | BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: ADDiu), DestReg: VR).addReg(RegNo: ZERO).addImm(Val: MaxAlign); |
512 | BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: AND), DestReg: SP).addReg(RegNo: SP).addReg(RegNo: VR); |
513 | |
514 | if (hasBP(MF)) { |
515 | // move $s7, $sp |
516 | unsigned BP = STI.isABI_N64() ? Mips::S7_64 : Mips::S7; |
517 | BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: MOVE), DestReg: BP) |
518 | .addReg(RegNo: SP) |
519 | .addReg(RegNo: ZERO); |
520 | } |
521 | } |
522 | } |
523 | } |
524 | |
525 | void MipsSEFrameLowering::emitInterruptPrologueStub( |
526 | MachineFunction &MF, MachineBasicBlock &MBB) const { |
527 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); |
528 | MachineBasicBlock::iterator MBBI = MBB.begin(); |
529 | DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); |
530 | |
531 | // Report an error the target doesn't support Mips32r2 or later. |
532 | // The epilogue relies on the use of the "ehb" to clear execution |
533 | // hazards. Pre R2 Mips relies on an implementation defined number |
534 | // of "ssnop"s to clear the execution hazard. Support for ssnop hazard |
535 | // clearing is not provided so reject that configuration. |
536 | if (!STI.hasMips32r2()) |
537 | report_fatal_error( |
538 | reason: "\"interrupt\" attribute is not supported on pre-MIPS32R2 or " |
539 | "MIPS16 targets." ); |
540 | |
541 | // The GP register contains the "user" value, so we cannot perform |
542 | // any gp relative loads until we restore the "kernel" or "system" gp |
543 | // value. Until support is written we shall only accept the static |
544 | // relocation model. |
545 | if ((STI.getRelocationModel() != Reloc::Static)) |
546 | report_fatal_error(reason: "\"interrupt\" attribute is only supported for the " |
547 | "static relocation model on MIPS at the present time." ); |
548 | |
549 | if (!STI.isABI_O32() || STI.hasMips64()) |
550 | report_fatal_error(reason: "\"interrupt\" attribute is only supported for the " |
551 | "O32 ABI on MIPS32R2+ at the present time." ); |
552 | |
553 | // Perform ISR handling like GCC |
554 | StringRef IntKind = |
555 | MF.getFunction().getFnAttribute(Kind: "interrupt" ).getValueAsString(); |
556 | const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass; |
557 | |
558 | // EIC interrupt handling needs to read the Cause register to disable |
559 | // interrupts. |
560 | if (IntKind == "eic" ) { |
561 | // Coprocessor registers are always live per se. |
562 | MBB.addLiveIn(PhysReg: Mips::COP013); |
563 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MFC0), DestReg: Mips::K0) |
564 | .addReg(RegNo: Mips::COP013) |
565 | .addImm(Val: 0) |
566 | .setMIFlag(MachineInstr::FrameSetup); |
567 | |
568 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::EXT), DestReg: Mips::K0) |
569 | .addReg(RegNo: Mips::K0) |
570 | .addImm(Val: 10) |
571 | .addImm(Val: 6) |
572 | .setMIFlag(MachineInstr::FrameSetup); |
573 | } |
574 | |
575 | // Fetch and spill EPC |
576 | MBB.addLiveIn(PhysReg: Mips::COP014); |
577 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MFC0), DestReg: Mips::K1) |
578 | .addReg(RegNo: Mips::COP014) |
579 | .addImm(Val: 0) |
580 | .setMIFlag(MachineInstr::FrameSetup); |
581 | |
582 | STI.getInstrInfo()->storeRegToStack(MBB, MI: MBBI, SrcReg: Mips::K1, isKill: false, |
583 | FrameIndex: MipsFI->getISRRegFI(Reg: 0), RC: PtrRC, |
584 | TRI: STI.getRegisterInfo(), Offset: 0); |
585 | |
586 | // Fetch and Spill Status |
587 | MBB.addLiveIn(PhysReg: Mips::COP012); |
588 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MFC0), DestReg: Mips::K1) |
589 | .addReg(RegNo: Mips::COP012) |
590 | .addImm(Val: 0) |
591 | .setMIFlag(MachineInstr::FrameSetup); |
592 | |
593 | STI.getInstrInfo()->storeRegToStack(MBB, MI: MBBI, SrcReg: Mips::K1, isKill: false, |
594 | FrameIndex: MipsFI->getISRRegFI(Reg: 1), RC: PtrRC, |
595 | TRI: STI.getRegisterInfo(), Offset: 0); |
596 | |
597 | // Build the configuration for disabling lower priority interrupts. Non EIC |
598 | // interrupts need to be masked off with zero, EIC from the Cause register. |
599 | unsigned InsPosition = 8; |
600 | unsigned InsSize = 0; |
601 | unsigned SrcReg = Mips::ZERO; |
602 | |
603 | // If the interrupt we're tied to is the EIC, switch the source for the |
604 | // masking off interrupts to the cause register. |
605 | if (IntKind == "eic" ) { |
606 | SrcReg = Mips::K0; |
607 | InsPosition = 10; |
608 | InsSize = 6; |
609 | } else |
610 | InsSize = StringSwitch<unsigned>(IntKind) |
611 | .Case(S: "sw0" , Value: 1) |
612 | .Case(S: "sw1" , Value: 2) |
613 | .Case(S: "hw0" , Value: 3) |
614 | .Case(S: "hw1" , Value: 4) |
615 | .Case(S: "hw2" , Value: 5) |
616 | .Case(S: "hw3" , Value: 6) |
617 | .Case(S: "hw4" , Value: 7) |
618 | .Case(S: "hw5" , Value: 8) |
619 | .Default(Value: 0); |
620 | assert(InsSize != 0 && "Unknown interrupt type!" ); |
621 | |
622 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::INS), DestReg: Mips::K1) |
623 | .addReg(RegNo: SrcReg) |
624 | .addImm(Val: InsPosition) |
625 | .addImm(Val: InsSize) |
626 | .addReg(RegNo: Mips::K1) |
627 | .setMIFlag(MachineInstr::FrameSetup); |
628 | |
629 | // Mask off KSU, ERL, EXL |
630 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::INS), DestReg: Mips::K1) |
631 | .addReg(RegNo: Mips::ZERO) |
632 | .addImm(Val: 1) |
633 | .addImm(Val: 4) |
634 | .addReg(RegNo: Mips::K1) |
635 | .setMIFlag(MachineInstr::FrameSetup); |
636 | |
637 | // Disable the FPU as we are not spilling those register sets. |
638 | if (!STI.useSoftFloat()) |
639 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::INS), DestReg: Mips::K1) |
640 | .addReg(RegNo: Mips::ZERO) |
641 | .addImm(Val: 29) |
642 | .addImm(Val: 1) |
643 | .addReg(RegNo: Mips::K1) |
644 | .setMIFlag(MachineInstr::FrameSetup); |
645 | |
646 | // Set the new status |
647 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MTC0), DestReg: Mips::COP012) |
648 | .addReg(RegNo: Mips::K1) |
649 | .addImm(Val: 0) |
650 | .setMIFlag(MachineInstr::FrameSetup); |
651 | } |
652 | |
653 | void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, |
654 | MachineBasicBlock &MBB) const { |
655 | MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); |
656 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
657 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); |
658 | |
659 | const MipsSEInstrInfo &TII = |
660 | *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo()); |
661 | const MipsRegisterInfo &RegInfo = |
662 | *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo()); |
663 | |
664 | DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); |
665 | MipsABIInfo ABI = STI.getABI(); |
666 | unsigned SP = ABI.GetStackPtr(); |
667 | unsigned FP = ABI.GetFramePtr(); |
668 | unsigned ZERO = ABI.GetNullPtr(); |
669 | unsigned MOVE = ABI.GetGPRMoveOp(); |
670 | |
671 | // if framepointer enabled, restore the stack pointer. |
672 | if (hasFP(MF)) { |
673 | // Find the first instruction that restores a callee-saved register. |
674 | MachineBasicBlock::iterator I = MBBI; |
675 | |
676 | for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i) |
677 | --I; |
678 | |
679 | // Insert instruction "move $sp, $fp" at this location. |
680 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: MOVE), DestReg: SP).addReg(RegNo: FP).addReg(RegNo: ZERO); |
681 | } |
682 | |
683 | if (MipsFI->callsEhReturn()) { |
684 | const TargetRegisterClass *RC = |
685 | ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; |
686 | |
687 | // Find first instruction that restores a callee-saved register. |
688 | MachineBasicBlock::iterator I = MBBI; |
689 | for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i) |
690 | --I; |
691 | |
692 | // Insert instructions that restore eh data registers. |
693 | for (int J = 0; J < 4; ++J) { |
694 | TII.loadRegFromStackSlot(MBB, MBBI: I, DestReg: ABI.GetEhDataReg(I: J), |
695 | FrameIndex: MipsFI->getEhDataRegFI(Reg: J), RC, TRI: &RegInfo, |
696 | VReg: Register()); |
697 | } |
698 | } |
699 | |
700 | if (MF.getFunction().hasFnAttribute(Kind: "interrupt" )) |
701 | emitInterruptEpilogueStub(MF, MBB); |
702 | |
703 | // Get the number of bytes from FrameInfo |
704 | uint64_t StackSize = MFI.getStackSize(); |
705 | |
706 | if (!StackSize) |
707 | return; |
708 | |
709 | // Adjust stack. |
710 | TII.adjustStackPtr(SP, Amount: StackSize, MBB, I: MBBI); |
711 | } |
712 | |
713 | void MipsSEFrameLowering::emitInterruptEpilogueStub( |
714 | MachineFunction &MF, MachineBasicBlock &MBB) const { |
715 | MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); |
716 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); |
717 | DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); |
718 | |
719 | // Perform ISR handling like GCC |
720 | const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass; |
721 | |
722 | // Disable Interrupts. |
723 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::DI), DestReg: Mips::ZERO); |
724 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::EHB)); |
725 | |
726 | // Restore EPC |
727 | STI.getInstrInfo()->loadRegFromStackSlot(MBB, MBBI, DestReg: Mips::K1, |
728 | FrameIndex: MipsFI->getISRRegFI(Reg: 0), RC: PtrRC, |
729 | TRI: STI.getRegisterInfo(), VReg: Register()); |
730 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MTC0), DestReg: Mips::COP014) |
731 | .addReg(RegNo: Mips::K1) |
732 | .addImm(Val: 0); |
733 | |
734 | // Restore Status |
735 | STI.getInstrInfo()->loadRegFromStackSlot(MBB, MBBI, DestReg: Mips::K1, |
736 | FrameIndex: MipsFI->getISRRegFI(Reg: 1), RC: PtrRC, |
737 | TRI: STI.getRegisterInfo(), VReg: Register()); |
738 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MTC0), DestReg: Mips::COP012) |
739 | .addReg(RegNo: Mips::K1) |
740 | .addImm(Val: 0); |
741 | } |
742 | |
743 | StackOffset |
744 | MipsSEFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, |
745 | Register &FrameReg) const { |
746 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
747 | MipsABIInfo ABI = STI.getABI(); |
748 | |
749 | if (MFI.isFixedObjectIndex(ObjectIdx: FI)) |
750 | FrameReg = hasFP(MF) ? ABI.GetFramePtr() : ABI.GetStackPtr(); |
751 | else |
752 | FrameReg = hasBP(MF) ? ABI.GetBasePtr() : ABI.GetStackPtr(); |
753 | |
754 | return StackOffset::getFixed(Fixed: MFI.getObjectOffset(ObjectIdx: FI) + MFI.getStackSize() - |
755 | getOffsetOfLocalArea() + |
756 | MFI.getOffsetAdjustment()); |
757 | } |
758 | |
759 | bool MipsSEFrameLowering::spillCalleeSavedRegisters( |
760 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
761 | ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { |
762 | MachineFunction *MF = MBB.getParent(); |
763 | const TargetInstrInfo &TII = *STI.getInstrInfo(); |
764 | |
765 | for (const CalleeSavedInfo &I : CSI) { |
766 | // Add the callee-saved register as live-in. Do not add if the register is |
767 | // RA and return address is taken, because it has already been added in |
768 | // method MipsTargetLowering::lowerRETURNADDR. |
769 | // It's killed at the spill, unless the register is RA and return address |
770 | // is taken. |
771 | MCRegister Reg = I.getReg(); |
772 | bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64) |
773 | && MF->getFrameInfo().isReturnAddressTaken(); |
774 | if (!IsRAAndRetAddrIsTaken) |
775 | MBB.addLiveIn(PhysReg: Reg); |
776 | |
777 | // ISRs require HI/LO to be spilled into kernel registers to be then |
778 | // spilled to the stack frame. |
779 | bool IsLOHI = (Reg == Mips::LO0 || Reg == Mips::LO0_64 || |
780 | Reg == Mips::HI0 || Reg == Mips::HI0_64); |
781 | const Function &Func = MBB.getParent()->getFunction(); |
782 | if (IsLOHI && Func.hasFnAttribute(Kind: "interrupt" )) { |
783 | DebugLoc DL = MI->getDebugLoc(); |
784 | |
785 | unsigned Op = 0; |
786 | if (!STI.getABI().ArePtrs64bit()) { |
787 | Op = (Reg == Mips::HI0) ? Mips::MFHI : Mips::MFLO; |
788 | Reg = Mips::K0; |
789 | } else { |
790 | Op = (Reg == Mips::HI0) ? Mips::MFHI64 : Mips::MFLO64; |
791 | Reg = Mips::K0_64; |
792 | } |
793 | BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: Op), DestReg: Mips::K0) |
794 | .setMIFlag(MachineInstr::FrameSetup); |
795 | } |
796 | |
797 | // Insert the spill to the stack frame. |
798 | bool IsKill = !IsRAAndRetAddrIsTaken; |
799 | const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); |
800 | TII.storeRegToStackSlot(MBB, MI, SrcReg: Reg, isKill: IsKill, FrameIndex: I.getFrameIdx(), RC, TRI, |
801 | VReg: Register()); |
802 | } |
803 | |
804 | return true; |
805 | } |
806 | |
807 | bool |
808 | MipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { |
809 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
810 | // Reserve call frame if the size of the maximum call frame fits into 16-bit |
811 | // immediate field and there are no variable sized objects on the stack. |
812 | // Make sure the second register scavenger spill slot can be accessed with one |
813 | // instruction. |
814 | return isInt<16>(x: MFI.getMaxCallFrameSize() + getStackAlignment()) && |
815 | !MFI.hasVarSizedObjects(); |
816 | } |
817 | |
818 | /// Mark \p Reg and all registers aliasing it in the bitset. |
819 | static void setAliasRegs(MachineFunction &MF, BitVector &SavedRegs, |
820 | unsigned Reg) { |
821 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); |
822 | for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) |
823 | SavedRegs.set(*AI); |
824 | } |
825 | |
826 | void MipsSEFrameLowering::determineCalleeSaves(MachineFunction &MF, |
827 | BitVector &SavedRegs, |
828 | RegScavenger *RS) const { |
829 | TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); |
830 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); |
831 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); |
832 | MipsABIInfo ABI = STI.getABI(); |
833 | unsigned RA = ABI.IsN64() ? Mips::RA_64 : Mips::RA; |
834 | unsigned FP = ABI.GetFramePtr(); |
835 | unsigned BP = ABI.IsN64() ? Mips::S7_64 : Mips::S7; |
836 | |
837 | // Mark $ra and $fp as used if function has dedicated frame pointer. |
838 | if (hasFP(MF)) { |
839 | setAliasRegs(MF, SavedRegs, Reg: RA); |
840 | setAliasRegs(MF, SavedRegs, Reg: FP); |
841 | } |
842 | // Mark $s7 as used if function has dedicated base pointer. |
843 | if (hasBP(MF)) |
844 | setAliasRegs(MF, SavedRegs, Reg: BP); |
845 | |
846 | // Create spill slots for eh data registers if function calls eh_return. |
847 | if (MipsFI->callsEhReturn()) |
848 | MipsFI->createEhDataRegsFI(MF); |
849 | |
850 | // Create spill slots for Coprocessor 0 registers if function is an ISR. |
851 | if (MipsFI->isISR()) |
852 | MipsFI->createISRRegFI(MF); |
853 | |
854 | // Expand pseudo instructions which load, store or copy accumulators. |
855 | // Add an emergency spill slot if a pseudo was expanded. |
856 | if (ExpandPseudo(MF).expand()) { |
857 | // The spill slot should be half the size of the accumulator. If target have |
858 | // general-purpose registers 64 bits wide, it should be 64-bit, otherwise |
859 | // it should be 32-bit. |
860 | const TargetRegisterClass &RC = STI.isGP64bit() ? |
861 | Mips::GPR64RegClass : Mips::GPR32RegClass; |
862 | int FI = MF.getFrameInfo().CreateSpillStackObject(Size: TRI->getSpillSize(RC), |
863 | Alignment: TRI->getSpillAlign(RC)); |
864 | RS->addScavengingFrameIndex(FI); |
865 | } |
866 | |
867 | // Set scavenging frame index if necessary. |
868 | uint64_t MaxSPOffset = estimateStackSize(MF); |
869 | |
870 | // MSA has a minimum offset of 10 bits signed. If there is a variable |
871 | // sized object on the stack, the estimation cannot account for it. |
872 | if (isIntN(N: STI.hasMSA() ? 10 : 16, x: MaxSPOffset) && |
873 | !MF.getFrameInfo().hasVarSizedObjects()) |
874 | return; |
875 | |
876 | const TargetRegisterClass &RC = |
877 | ABI.ArePtrs64bit() ? Mips::GPR64RegClass : Mips::GPR32RegClass; |
878 | int FI = MF.getFrameInfo().CreateSpillStackObject(Size: TRI->getSpillSize(RC), |
879 | Alignment: TRI->getSpillAlign(RC)); |
880 | RS->addScavengingFrameIndex(FI); |
881 | } |
882 | |
883 | const MipsFrameLowering * |
884 | llvm::createMipsSEFrameLowering(const MipsSubtarget &ST) { |
885 | return new MipsSEFrameLowering(ST); |
886 | } |
887 | |