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, 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
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, TRI: &RegInfo, 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, 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
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 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
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 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.
284bool 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.
340bool 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
396MipsSEFrameLowering::MipsSEFrameLowering(const MipsSubtarget &STI)
397 : MipsFrameLowering(STI, STI.getStackAlignment()) {}
398
399void 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
525void 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
653void 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
713void 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
743StackOffset
744MipsSEFrameLowering::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
759bool 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
807bool
808MipsSEFrameLowering::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.
819static 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
826void 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
883const MipsFrameLowering *
884llvm::createMipsSEFrameLowering(const MipsSubtarget &ST) {
885 return new MipsSEFrameLowering(ST);
886}
887