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