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
45using namespace llvm;
46
47static 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
62namespace {
63
64/// Helper class to expand pseudos.
65class ExpandPseudo {
66public:
67 ExpandPseudo(MachineFunction &MF);
68 bool expand();
69
70private:
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
96ExpandPseudo::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
102bool 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
113bool 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
165void 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, 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
180void 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, Offset: 0);
193}
194
195void 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, 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, Offset: RegSize);
216 BuildMI(BB&: MBB, I, MIMD: DL, MCID: Desc, DestReg: Hi).addReg(RegNo: VR1, Flags: RegState::Kill);
217}
218
219void 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 RegState 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, 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, Offset: RegSize);
240}
241
242bool 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
252bool 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 RegState 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 FPXX/FP64 when mthc1 is not available and
281/// for FP64A. It is implemented here
282/// because frame indexes are eliminated before MipsSEInstrInfo::
283/// expandBuildPairF64 is called.
284bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB,
285 MachineBasicBlock::iterator I,
286 bool FP64) const {
287 // For FPXX/FP64 when mthc1 is not available, use:
288 // spill + reload via ldc1
289 //
290 // The case where 64-bit GPRs can be used 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 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
310 const TargetRegisterClass *RC2 =
311 FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
312
313 // We re-use the same spill slot each time so that the stack frame doesn't
314 // grow too much in functions with a large number of moves.
315 int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(MF, RC: RC2);
316 if (!Subtarget.isLittle())
317 std::swap(a&: LoReg, b&: HiReg);
318 TII.storeRegToStack(MBB, MI: I, SrcReg: LoReg, isKill: I->getOperand(i: 1).isKill(), FrameIndex: FI, RC, Offset: 0);
319 TII.storeRegToStack(MBB, MI: I, SrcReg: HiReg, isKill: I->getOperand(i: 2).isKill(), FrameIndex: FI, RC, Offset: 4);
320 TII.loadRegFromStack(MBB, MI: I, DestReg: DstReg, FrameIndex: FI, RC: RC2, Offset: 0);
321 return true;
322 }
323
324 return false;
325}
326
327/// This method expands the same instruction that MipsSEInstrInfo::
328/// expandExtractElementF64 does, for FPXX/FP64 when mfhc1 is not available and
329/// for FP64A. It is implemented here
330/// because frame indexes are eliminated before MipsSEInstrInfo::
331/// expandExtractElementF64 is called.
332bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB,
333 MachineBasicBlock::iterator I,
334 bool FP64) const {
335 const MachineOperand &Op1 = I->getOperand(i: 1);
336 const MachineOperand &Op2 = I->getOperand(i: 2);
337
338 if ((Op1.isReg() && Op1.isUndef()) || (Op2.isReg() && Op2.isUndef())) {
339 Register DstReg = I->getOperand(i: 0).getReg();
340 BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: TII.get(Opcode: Mips::IMPLICIT_DEF), DestReg: DstReg);
341 return true;
342 }
343
344 // For FPXX/FP64 when mfhc1 is not available, use:
345 // spill + reload via ldc1
346 //
347 // The case where 64-bit GPRs can be used doesn't need to be handled here
348 // because it never creates a ExtractElementF64 node.
349 //
350 // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence
351 // for odd-numbered double precision values (because the lower 32-bits is
352 // transferred with mfc1 which is redirected to the upper half of the even
353 // register). Unfortunately, we have to make this decision before register
354 // allocation so for now we use a spill/reload sequence for all
355 // double-precision values in regardless of being an odd/even register.
356 //
357 // For the cases that should be covered here MipsSEISelDAGToDAG adds $sp as
358 // implicit operand, so other passes (like ShrinkWrapping) are aware that
359 // stack is used.
360 if (I->getNumOperands() == 4 && I->getOperand(i: 3).isReg()
361 && I->getOperand(i: 3).getReg() == Mips::SP) {
362 Register DstReg = I->getOperand(i: 0).getReg();
363 Register SrcReg = Op1.getReg();
364 unsigned N = Op2.getImm();
365 int64_t Offset = 4 * (Subtarget.isLittle() ? N : (1 - N));
366
367 const TargetRegisterClass *RC =
368 FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
369 const TargetRegisterClass *RC2 = &Mips::GPR32RegClass;
370
371 // We re-use the same spill slot each time so that the stack frame doesn't
372 // grow too much in functions with a large number of moves.
373 int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(MF, RC);
374 TII.storeRegToStack(MBB, MI: I, SrcReg, isKill: Op1.isKill(), FrameIndex: FI, RC, Offset: 0);
375 TII.loadRegFromStack(MBB, MI: I, DestReg: DstReg, FrameIndex: FI, RC: RC2, Offset);
376 return true;
377 }
378
379 return false;
380}
381
382MipsSEFrameLowering::MipsSEFrameLowering(const MipsSubtarget &STI)
383 : MipsFrameLowering(STI, STI.getStackAlignment()) {}
384
385void MipsSEFrameLowering::emitPrologue(MachineFunction &MF,
386 MachineBasicBlock &MBB) const {
387 MachineFrameInfo &MFI = MF.getFrameInfo();
388 MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
389
390 const MipsSEInstrInfo &TII =
391 *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo());
392 const MipsRegisterInfo &RegInfo = *STI.getRegisterInfo();
393
394 MachineBasicBlock::iterator MBBI = MBB.begin();
395 DebugLoc dl;
396 MipsABIInfo ABI = STI.getABI();
397 unsigned SP = ABI.GetStackPtr();
398 unsigned FP = ABI.GetFramePtr();
399 unsigned ZERO = ABI.GetNullPtr();
400 unsigned MOVE = ABI.GetGPRMoveOp();
401 unsigned ADDiu = ABI.GetPtrAddiuOp();
402 unsigned AND = ABI.IsN64() ? Mips::AND64 : Mips::AND;
403
404 const TargetRegisterClass *RC = ABI.ArePtrs64bit() ?
405 &Mips::GPR64RegClass : &Mips::GPR32RegClass;
406
407 // First, compute final stack size.
408 uint64_t StackSize = MFI.getStackSize();
409
410 // No need to allocate space on the stack.
411 if (StackSize == 0 && !MFI.adjustsStack()) return;
412
413 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::NoFlags);
414
415 // Adjust stack.
416 TII.adjustStackPtr(SP, Amount: -StackSize, MBB, I: MBBI);
417 CFIBuilder.buildDefCFAOffset(Offset: StackSize);
418
419 if (MF.getFunction().hasFnAttribute(Kind: "interrupt"))
420 emitInterruptPrologueStub(MF, MBB);
421
422 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
423
424 // Find the instruction past the last instruction that saves a callee-saved
425 // register to the stack.
426 std::advance(i&: MBBI, n: CSI.size());
427 CFIBuilder.setInsertPoint(MBBI);
428
429 if (!CSI.empty()) {
430 // Iterate over list of callee-saved registers and emit .cfi_offset
431 // directives.
432 for (const CalleeSavedInfo &I : CSI) {
433 int64_t Offset = MFI.getObjectOffset(ObjectIdx: I.getFrameIdx());
434 MCRegister Reg = I.getReg();
435
436 // If Reg is a double precision register, emit two cfa_offsets,
437 // one for each of the paired single precision registers.
438 if (Mips::AFGR64RegClass.contains(Reg)) {
439 MCRegister Reg0 = RegInfo.getSubReg(Reg, Idx: Mips::sub_lo);
440 MCRegister Reg1 = RegInfo.getSubReg(Reg, Idx: Mips::sub_hi);
441
442 if (!STI.isLittle())
443 std::swap(a&: Reg0, b&: Reg1);
444
445 CFIBuilder.buildOffset(Reg: Reg0, Offset);
446 CFIBuilder.buildOffset(Reg: Reg1, Offset: Offset + 4);
447 } else if (Mips::FGR64RegClass.contains(Reg)) {
448 MCRegister Reg0 = Reg;
449 MCRegister Reg1 = Reg + 1;
450
451 if (!STI.isLittle())
452 std::swap(a&: Reg0, b&: Reg1);
453
454 CFIBuilder.buildOffset(Reg: Reg0, Offset);
455 CFIBuilder.buildOffset(Reg: Reg1, Offset: Offset + 4);
456 } else {
457 // Reg is either in GPR32 or FGR32.
458 CFIBuilder.buildOffset(Reg, Offset);
459 }
460 }
461 }
462
463 if (MipsFI->callsEhReturn()) {
464 // Insert instructions that spill eh data registers.
465 for (int I = 0; I < 4; ++I) {
466 if (!MBB.isLiveIn(Reg: ABI.GetEhDataReg(I)))
467 MBB.addLiveIn(PhysReg: ABI.GetEhDataReg(I));
468 TII.storeRegToStackSlot(MBB, MBBI, SrcReg: ABI.GetEhDataReg(I), isKill: false,
469 FrameIndex: MipsFI->getEhDataRegFI(Reg: I), RC, VReg: Register());
470 }
471
472 // Emit .cfi_offset directives for eh data registers.
473 for (int I = 0; I < 4; ++I) {
474 int64_t Offset = MFI.getObjectOffset(ObjectIdx: MipsFI->getEhDataRegFI(Reg: I));
475 CFIBuilder.buildOffset(Reg: ABI.GetEhDataReg(I), Offset);
476 }
477 }
478
479 // if framepointer enabled, set it to point to the stack pointer.
480 if (hasFP(MF)) {
481 // Insert instruction "move $fp, $sp" at this location.
482 BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: MOVE), DestReg: FP).addReg(RegNo: SP).addReg(RegNo: ZERO)
483 .setMIFlag(MachineInstr::FrameSetup);
484
485 CFIBuilder.buildDefCFARegister(Reg: FP);
486
487 if (RegInfo.hasStackRealignment(MF)) {
488 // addiu $Reg, $zero, -MaxAlignment
489 // andi $sp, $sp, $Reg
490 Register VR = MF.getRegInfo().createVirtualRegister(RegClass: RC);
491 assert((Log2(MFI.getMaxAlign()) < 16) &&
492 "Function's alignment size requirement is not supported.");
493 int64_t MaxAlign = -(int64_t)MFI.getMaxAlign().value();
494
495 BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: ADDiu), DestReg: VR).addReg(RegNo: ZERO).addImm(Val: MaxAlign);
496 BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: AND), DestReg: SP).addReg(RegNo: SP).addReg(RegNo: VR);
497
498 if (hasBP(MF)) {
499 // move $s7, $sp
500 unsigned BP = STI.getABI().GetBasePtr();
501 BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: MOVE), DestReg: BP)
502 .addReg(RegNo: SP)
503 .addReg(RegNo: ZERO);
504 }
505 }
506 }
507}
508
509void MipsSEFrameLowering::emitInterruptPrologueStub(
510 MachineFunction &MF, MachineBasicBlock &MBB) const {
511 MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
512 MachineBasicBlock::iterator MBBI = MBB.begin();
513 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
514
515 // Report an error the target doesn't support Mips32r2 or later.
516 // The epilogue relies on the use of the "ehb" to clear execution
517 // hazards. Pre R2 Mips relies on an implementation defined number
518 // of "ssnop"s to clear the execution hazard. Support for ssnop hazard
519 // clearing is not provided so reject that configuration.
520 if (!STI.hasMips32r2())
521 report_fatal_error(
522 reason: "\"interrupt\" attribute is not supported on pre-MIPS32R2 or "
523 "MIPS16 targets.");
524
525 // The GP register contains the "user" value, so we cannot perform
526 // any gp relative loads until we restore the "kernel" or "system" gp
527 // value. Until support is written we shall only accept the static
528 // relocation model.
529 if ((STI.getRelocationModel() != Reloc::Static))
530 report_fatal_error(reason: "\"interrupt\" attribute is only supported for the "
531 "static relocation model on MIPS at the present time.");
532
533 if (!STI.isABI_O32() || STI.hasMips64())
534 report_fatal_error(reason: "\"interrupt\" attribute is only supported for the "
535 "O32 ABI on MIPS32R2+ at the present time.");
536
537 // Perform ISR handling like GCC
538 StringRef IntKind =
539 MF.getFunction().getFnAttribute(Kind: "interrupt").getValueAsString();
540 const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass;
541
542 // EIC interrupt handling needs to read the Cause register to disable
543 // interrupts.
544 if (IntKind == "eic") {
545 // Coprocessor registers are always live per se.
546 MBB.addLiveIn(PhysReg: Mips::COP013);
547 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MFC0), DestReg: Mips::K0)
548 .addReg(RegNo: Mips::COP013)
549 .addImm(Val: 0)
550 .setMIFlag(MachineInstr::FrameSetup);
551
552 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::EXT), DestReg: Mips::K0)
553 .addReg(RegNo: Mips::K0)
554 .addImm(Val: 10)
555 .addImm(Val: 6)
556 .setMIFlag(MachineInstr::FrameSetup);
557 }
558
559 // Fetch and spill EPC
560 MBB.addLiveIn(PhysReg: Mips::COP014);
561 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MFC0), DestReg: Mips::K1)
562 .addReg(RegNo: Mips::COP014)
563 .addImm(Val: 0)
564 .setMIFlag(MachineInstr::FrameSetup);
565
566 STI.getInstrInfo()->storeRegToStack(MBB, MI: MBBI, SrcReg: Mips::K1, isKill: false,
567 FrameIndex: MipsFI->getISRRegFI(Reg: 0), RC: PtrRC, Offset: 0);
568
569 // Fetch and Spill Status
570 MBB.addLiveIn(PhysReg: Mips::COP012);
571 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MFC0), DestReg: Mips::K1)
572 .addReg(RegNo: Mips::COP012)
573 .addImm(Val: 0)
574 .setMIFlag(MachineInstr::FrameSetup);
575
576 STI.getInstrInfo()->storeRegToStack(MBB, MI: MBBI, SrcReg: Mips::K1, isKill: false,
577 FrameIndex: MipsFI->getISRRegFI(Reg: 1), RC: PtrRC, Offset: 0);
578
579 // Build the configuration for disabling lower priority interrupts. Non EIC
580 // interrupts need to be masked off with zero, EIC from the Cause register.
581 unsigned InsPosition = 8;
582 unsigned InsSize = 0;
583 unsigned SrcReg = Mips::ZERO;
584
585 // If the interrupt we're tied to is the EIC, switch the source for the
586 // masking off interrupts to the cause register.
587 if (IntKind == "eic") {
588 SrcReg = Mips::K0;
589 InsPosition = 10;
590 InsSize = 6;
591 } else
592 InsSize = StringSwitch<unsigned>(IntKind)
593 .Case(S: "sw0", Value: 1)
594 .Case(S: "sw1", Value: 2)
595 .Case(S: "hw0", Value: 3)
596 .Case(S: "hw1", Value: 4)
597 .Case(S: "hw2", Value: 5)
598 .Case(S: "hw3", Value: 6)
599 .Case(S: "hw4", Value: 7)
600 .Case(S: "hw5", Value: 8)
601 .Default(Value: 0);
602 assert(InsSize != 0 && "Unknown interrupt type!");
603
604 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::INS), DestReg: Mips::K1)
605 .addReg(RegNo: SrcReg)
606 .addImm(Val: InsPosition)
607 .addImm(Val: InsSize)
608 .addReg(RegNo: Mips::K1)
609 .setMIFlag(MachineInstr::FrameSetup);
610
611 // Mask off KSU, ERL, EXL
612 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::INS), DestReg: Mips::K1)
613 .addReg(RegNo: Mips::ZERO)
614 .addImm(Val: 1)
615 .addImm(Val: 4)
616 .addReg(RegNo: Mips::K1)
617 .setMIFlag(MachineInstr::FrameSetup);
618
619 // Disable the FPU as we are not spilling those register sets.
620 if (!STI.useSoftFloat())
621 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::INS), DestReg: Mips::K1)
622 .addReg(RegNo: Mips::ZERO)
623 .addImm(Val: 29)
624 .addImm(Val: 1)
625 .addReg(RegNo: Mips::K1)
626 .setMIFlag(MachineInstr::FrameSetup);
627
628 // Set the new status
629 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MTC0), DestReg: Mips::COP012)
630 .addReg(RegNo: Mips::K1)
631 .addImm(Val: 0)
632 .setMIFlag(MachineInstr::FrameSetup);
633}
634
635void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF,
636 MachineBasicBlock &MBB) const {
637 MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
638 MachineFrameInfo &MFI = MF.getFrameInfo();
639 MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
640
641 const MipsSEInstrInfo &TII =
642 *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo());
643
644 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
645 MipsABIInfo ABI = STI.getABI();
646 unsigned SP = ABI.GetStackPtr();
647 unsigned FP = ABI.GetFramePtr();
648 unsigned ZERO = ABI.GetNullPtr();
649 unsigned MOVE = ABI.GetGPRMoveOp();
650
651 // if framepointer enabled, restore the stack pointer.
652 if (hasFP(MF)) {
653 // Find the first instruction that restores a callee-saved register.
654 MachineBasicBlock::iterator I = MBBI;
655
656 for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i)
657 --I;
658
659 // Insert instruction "move $sp, $fp" at this location.
660 BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: MOVE), DestReg: SP).addReg(RegNo: FP).addReg(RegNo: ZERO);
661 }
662
663 if (MipsFI->callsEhReturn()) {
664 const TargetRegisterClass *RC =
665 ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
666
667 // Find first instruction that restores a callee-saved register.
668 MachineBasicBlock::iterator I = MBBI;
669 for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i)
670 --I;
671
672 // Insert instructions that restore eh data registers.
673 for (int J = 0; J < 4; ++J) {
674 TII.loadRegFromStackSlot(MBB, MBBI: I, DestReg: ABI.GetEhDataReg(I: J),
675 FrameIndex: MipsFI->getEhDataRegFI(Reg: J), RC, VReg: Register());
676 }
677 }
678
679 if (MF.getFunction().hasFnAttribute(Kind: "interrupt"))
680 emitInterruptEpilogueStub(MF, MBB);
681
682 // Get the number of bytes from FrameInfo
683 uint64_t StackSize = MFI.getStackSize();
684
685 if (!StackSize)
686 return;
687
688 // Adjust stack.
689 TII.adjustStackPtr(SP, Amount: StackSize, MBB, I: MBBI);
690}
691
692void MipsSEFrameLowering::emitInterruptEpilogueStub(
693 MachineFunction &MF, MachineBasicBlock &MBB) const {
694 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
695 MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
696 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
697
698 // Perform ISR handling like GCC
699 const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass;
700
701 // Disable Interrupts.
702 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::DI), DestReg: Mips::ZERO);
703 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::EHB));
704
705 // Restore EPC
706 STI.getInstrInfo()->loadRegFromStackSlot(
707 MBB, MBBI, DestReg: Mips::K1, FrameIndex: MipsFI->getISRRegFI(Reg: 0), RC: PtrRC, VReg: Register());
708 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MTC0), DestReg: Mips::COP014)
709 .addReg(RegNo: Mips::K1)
710 .addImm(Val: 0);
711
712 // Restore Status
713 STI.getInstrInfo()->loadRegFromStackSlot(
714 MBB, MBBI, DestReg: Mips::K1, FrameIndex: MipsFI->getISRRegFI(Reg: 1), RC: PtrRC, VReg: Register());
715 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MTC0), DestReg: Mips::COP012)
716 .addReg(RegNo: Mips::K1)
717 .addImm(Val: 0);
718}
719
720StackOffset
721MipsSEFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
722 Register &FrameReg) const {
723 const MachineFrameInfo &MFI = MF.getFrameInfo();
724 MipsABIInfo ABI = STI.getABI();
725
726 if (MFI.isFixedObjectIndex(ObjectIdx: FI))
727 FrameReg = hasFP(MF) ? ABI.GetFramePtr() : ABI.GetStackPtr();
728 else
729 FrameReg = hasBP(MF) ? ABI.GetBasePtr() : ABI.GetStackPtr();
730
731 return StackOffset::getFixed(Fixed: MFI.getObjectOffset(ObjectIdx: FI) + MFI.getStackSize() -
732 getOffsetOfLocalArea() +
733 MFI.getOffsetAdjustment());
734}
735
736bool MipsSEFrameLowering::spillCalleeSavedRegisters(
737 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
738 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
739 MachineFunction *MF = MBB.getParent();
740 const TargetInstrInfo &TII = *STI.getInstrInfo();
741
742 for (const CalleeSavedInfo &I : CSI) {
743 // Add the callee-saved register as live-in. Do not add if the register is
744 // RA and return address is taken, because it has already been added in
745 // method MipsTargetLowering::lowerRETURNADDR.
746 // It's killed at the spill, unless the register is RA and return address
747 // is taken.
748 MCRegister Reg = I.getReg();
749 bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64)
750 && MF->getFrameInfo().isReturnAddressTaken();
751 if (!IsRAAndRetAddrIsTaken)
752 MBB.addLiveIn(PhysReg: Reg);
753
754 // ISRs require HI/LO to be spilled into kernel registers to be then
755 // spilled to the stack frame.
756 bool IsLOHI = (Reg == Mips::LO0 || Reg == Mips::LO0_64 ||
757 Reg == Mips::HI0 || Reg == Mips::HI0_64);
758 const Function &Func = MBB.getParent()->getFunction();
759 if (IsLOHI && Func.hasFnAttribute(Kind: "interrupt")) {
760 DebugLoc DL = MI->getDebugLoc();
761
762 unsigned Op = 0;
763 if (!STI.getABI().ArePtrs64bit()) {
764 Op = (Reg == Mips::HI0) ? Mips::MFHI : Mips::MFLO;
765 Reg = Mips::K0;
766 } else {
767 Op = (Reg == Mips::HI0) ? Mips::MFHI64 : Mips::MFLO64;
768 Reg = Mips::K0_64;
769 }
770 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: Op), DestReg: Mips::K0)
771 .setMIFlag(MachineInstr::FrameSetup);
772 }
773
774 // Insert the spill to the stack frame.
775 bool IsKill = !IsRAAndRetAddrIsTaken;
776 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
777 TII.storeRegToStackSlot(MBB, MI, SrcReg: Reg, isKill: IsKill, FrameIndex: I.getFrameIdx(), RC,
778 VReg: Register());
779 }
780
781 return true;
782}
783
784bool
785MipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
786 const MachineFrameInfo &MFI = MF.getFrameInfo();
787 // Reserve call frame if the size of the maximum call frame fits into 16-bit
788 // immediate field and there are no variable sized objects on the stack.
789 // Make sure the second register scavenger spill slot can be accessed with one
790 // instruction.
791 return isInt<16>(x: MFI.getMaxCallFrameSize() + getStackAlignment()) &&
792 !MFI.hasVarSizedObjects();
793}
794
795/// Mark \p Reg and all registers aliasing it in the bitset.
796static void setAliasRegs(MachineFunction &MF, BitVector &SavedRegs,
797 unsigned Reg) {
798 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
799 for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
800 SavedRegs.set(*AI);
801}
802
803void MipsSEFrameLowering::determineCalleeSaves(MachineFunction &MF,
804 BitVector &SavedRegs,
805 RegScavenger *RS) const {
806 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
807 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
808 MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
809 MipsABIInfo ABI = STI.getABI();
810 unsigned RA = ABI.IsN64() ? Mips::RA_64 : Mips::RA;
811 unsigned FP = ABI.GetFramePtr();
812 unsigned BP = ABI.GetBasePtr();
813
814 // Mark $ra and $fp as used if function has dedicated frame pointer.
815 if (hasFP(MF)) {
816 setAliasRegs(MF, SavedRegs, Reg: RA);
817 setAliasRegs(MF, SavedRegs, Reg: FP);
818 }
819 // Mark $s7 as used if function has dedicated base pointer.
820 if (hasBP(MF))
821 setAliasRegs(MF, SavedRegs, Reg: BP);
822
823 // Create spill slots for eh data registers if function calls eh_return.
824 if (MipsFI->callsEhReturn())
825 MipsFI->createEhDataRegsFI(MF);
826
827 // Create spill slots for Coprocessor 0 registers if function is an ISR.
828 if (MipsFI->isISR())
829 MipsFI->createISRRegFI(MF);
830
831 // Expand pseudo instructions which load, store or copy accumulators.
832 // Add an emergency spill slot if a pseudo was expanded.
833 if (ExpandPseudo(MF).expand()) {
834 // The spill slot should be half the size of the accumulator. If target have
835 // general-purpose registers 64 bits wide, it should be 64-bit, otherwise
836 // it should be 32-bit.
837 const TargetRegisterClass &RC = STI.isGP64bit() ?
838 Mips::GPR64RegClass : Mips::GPR32RegClass;
839 int FI = MF.getFrameInfo().CreateSpillStackObject(Size: TRI->getSpillSize(RC),
840 Alignment: TRI->getSpillAlign(RC));
841 RS->addScavengingFrameIndex(FI);
842 }
843
844 // Set scavenging frame index if necessary.
845 uint64_t MaxSPOffset = estimateStackSize(MF);
846
847 // MSA has a minimum offset of 10 bits signed. If there is a variable
848 // sized object on the stack, the estimation cannot account for it.
849 if (isIntN(N: STI.hasMSA() ? 10 : 16, x: MaxSPOffset) &&
850 !MF.getFrameInfo().hasVarSizedObjects())
851 return;
852
853 const TargetRegisterClass &RC =
854 ABI.ArePtrs64bit() ? Mips::GPR64RegClass : Mips::GPR32RegClass;
855 int FI = MF.getFrameInfo().CreateSpillStackObject(Size: TRI->getSpillSize(RC),
856 Alignment: TRI->getSpillAlign(RC));
857 RS->addScavengingFrameIndex(FI);
858}
859
860const MipsFrameLowering *
861llvm::createMipsSEFrameLowering(const MipsSubtarget &ST) {
862 return new MipsSEFrameLowering(ST);
863}
864