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