MipsSERegisterInfo.cpp revision 360784
1//===-- MipsSERegisterInfo.cpp - MIPS32/64 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 MIPS32/64 implementation of the TargetRegisterInfo
10// class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "MipsSERegisterInfo.h"
15#include "Mips.h"
16#include "MipsMachineFunction.h"
17#include "MipsSEInstrInfo.h"
18#include "MipsSubtarget.h"
19#include "MipsTargetMachine.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/CodeGen/MachineFrameInfo.h"
22#include "llvm/CodeGen/MachineFunction.h"
23#include "llvm/CodeGen/MachineInstrBuilder.h"
24#include "llvm/CodeGen/MachineRegisterInfo.h"
25#include "llvm/CodeGen/TargetFrameLowering.h"
26#include "llvm/CodeGen/TargetInstrInfo.h"
27#include "llvm/IR/Constants.h"
28#include "llvm/IR/DebugInfo.h"
29#include "llvm/IR/Function.h"
30#include "llvm/IR/Type.h"
31#include "llvm/Support/Debug.h"
32#include "llvm/Support/ErrorHandling.h"
33#include "llvm/Support/raw_ostream.h"
34#include "llvm/Target/TargetMachine.h"
35#include "llvm/Target/TargetOptions.h"
36
37using namespace llvm;
38
39#define DEBUG_TYPE "mips-reg-info"
40
41MipsSERegisterInfo::MipsSERegisterInfo() : MipsRegisterInfo() {}
42
43bool MipsSERegisterInfo::
44requiresRegisterScavenging(const MachineFunction &MF) const {
45  return true;
46}
47
48bool MipsSERegisterInfo::
49requiresFrameIndexScavenging(const MachineFunction &MF) const {
50  return true;
51}
52
53const TargetRegisterClass *
54MipsSERegisterInfo::intRegClass(unsigned Size) const {
55  if (Size == 4)
56    return &Mips::GPR32RegClass;
57
58  assert(Size == 8);
59  return &Mips::GPR64RegClass;
60}
61
62/// Get the size of the offset supported by the given load/store/inline asm.
63/// The result includes the effects of any scale factors applied to the
64/// instruction immediate.
65static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode,
66                                                    MachineOperand MO) {
67  switch (Opcode) {
68  case Mips::LD_B:
69  case Mips::ST_B:
70    return 10;
71  case Mips::LD_H:
72  case Mips::ST_H:
73    return 10 + 1 /* scale factor */;
74  case Mips::LD_W:
75  case Mips::ST_W:
76    return 10 + 2 /* scale factor */;
77  case Mips::LD_D:
78  case Mips::ST_D:
79    return 10 + 3 /* scale factor */;
80  case Mips::LL:
81  case Mips::LL64:
82  case Mips::LLD:
83  case Mips::LLE:
84  case Mips::SC:
85  case Mips::SC64:
86  case Mips::SCD:
87  case Mips::SCE:
88    return 16;
89  case Mips::LLE_MM:
90  case Mips::LL_MM:
91  case Mips::SCE_MM:
92  case Mips::SC_MM:
93    return 12;
94  case Mips::LL64_R6:
95  case Mips::LL_R6:
96  case Mips::LLD_R6:
97  case Mips::SC64_R6:
98  case Mips::SCD_R6:
99  case Mips::SC_R6:
100  case Mips::LL_MMR6:
101  case Mips::SC_MMR6:
102    return 9;
103  case Mips::INLINEASM: {
104    unsigned ConstraintID = InlineAsm::getMemoryConstraintID(MO.getImm());
105    switch (ConstraintID) {
106    case InlineAsm::Constraint_ZC: {
107      const MipsSubtarget &Subtarget = MO.getParent()
108                                           ->getParent()
109                                           ->getParent()
110                                           ->getSubtarget<MipsSubtarget>();
111      if (Subtarget.inMicroMipsMode())
112        return 12;
113
114      if (Subtarget.hasMips32r6())
115        return 9;
116
117      return 16;
118    }
119    default:
120      return 16;
121    }
122  }
123  default:
124    return 16;
125  }
126}
127
128/// Get the scale factor applied to the immediate in the given load/store.
129static inline unsigned getLoadStoreOffsetAlign(const unsigned Opcode) {
130  switch (Opcode) {
131  case Mips::LD_H:
132  case Mips::ST_H:
133    return 2;
134  case Mips::LD_W:
135  case Mips::ST_W:
136    return 4;
137  case Mips::LD_D:
138  case Mips::ST_D:
139    return 8;
140  default:
141    return 1;
142  }
143}
144
145void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
146                                     unsigned OpNo, int FrameIndex,
147                                     uint64_t StackSize,
148                                     int64_t SPOffset) const {
149  MachineInstr &MI = *II;
150  MachineFunction &MF = *MI.getParent()->getParent();
151  MachineFrameInfo &MFI = MF.getFrameInfo();
152  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
153
154  MipsABIInfo ABI =
155      static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI();
156  const MipsRegisterInfo *RegInfo =
157    static_cast<const MipsRegisterInfo *>(MF.getSubtarget().getRegisterInfo());
158
159  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
160  int MinCSFI = 0;
161  int MaxCSFI = -1;
162
163  if (CSI.size()) {
164    MinCSFI = CSI[0].getFrameIdx();
165    MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
166  }
167
168  bool EhDataRegFI = MipsFI->isEhDataRegFI(FrameIndex);
169  bool IsISRRegFI = MipsFI->isISRRegFI(FrameIndex);
170  // The following stack frame objects are always referenced relative to $sp:
171  //  1. Outgoing arguments.
172  //  2. Pointer to dynamically allocated stack space.
173  //  3. Locations for callee-saved registers.
174  //  4. Locations for eh data registers.
175  //  5. Locations for ISR saved Coprocessor 0 registers 12 & 14.
176  // Everything else is referenced relative to whatever register
177  // getFrameRegister() returns.
178  unsigned FrameReg;
179
180  if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) || EhDataRegFI ||
181      IsISRRegFI)
182    FrameReg = ABI.GetStackPtr();
183  else if (RegInfo->needsStackRealignment(MF)) {
184    if (MFI.hasVarSizedObjects() && !MFI.isFixedObjectIndex(FrameIndex))
185      FrameReg = ABI.GetBasePtr();
186    else if (MFI.isFixedObjectIndex(FrameIndex))
187      FrameReg = getFrameRegister(MF);
188    else
189      FrameReg = ABI.GetStackPtr();
190  } else
191    FrameReg = getFrameRegister(MF);
192
193  // Calculate final offset.
194  // - There is no need to change the offset if the frame object is one of the
195  //   following: an outgoing argument, pointer to a dynamically allocated
196  //   stack space or a $gp restore location,
197  // - If the frame object is any of the following, its offset must be adjusted
198  //   by adding the size of the stack:
199  //   incoming argument, callee-saved register location or local variable.
200  bool IsKill = false;
201  int64_t Offset;
202
203  Offset = SPOffset + (int64_t)StackSize;
204  Offset += MI.getOperand(OpNo + 1).getImm();
205
206  LLVM_DEBUG(errs() << "Offset     : " << Offset << "\n"
207                    << "<--------->\n");
208
209  if (!MI.isDebugValue()) {
210    // Make sure Offset fits within the field available.
211    // For MSA instructions, this is a 10-bit signed immediate (scaled by
212    // element size), otherwise it is a 16-bit signed immediate.
213    unsigned OffsetBitSize =
214        getLoadStoreOffsetSizeInBits(MI.getOpcode(), MI.getOperand(OpNo - 1));
215    const Align OffsetAlign(getLoadStoreOffsetAlign(MI.getOpcode()));
216    if (OffsetBitSize < 16 && isInt<16>(Offset) &&
217        (!isIntN(OffsetBitSize, Offset) || !isAligned(OffsetAlign, Offset))) {
218      // If we have an offset that needs to fit into a signed n-bit immediate
219      // (where n < 16) and doesn't, but does fit into 16-bits then use an ADDiu
220      MachineBasicBlock &MBB = *MI.getParent();
221      DebugLoc DL = II->getDebugLoc();
222      const TargetRegisterClass *PtrRC =
223          ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
224      MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
225      Register Reg = RegInfo.createVirtualRegister(PtrRC);
226      const MipsSEInstrInfo &TII =
227          *static_cast<const MipsSEInstrInfo *>(
228              MBB.getParent()->getSubtarget().getInstrInfo());
229      BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAddiuOp()), Reg)
230          .addReg(FrameReg)
231          .addImm(Offset);
232
233      FrameReg = Reg;
234      Offset = 0;
235      IsKill = true;
236    } else if (!isInt<16>(Offset)) {
237      // Otherwise split the offset into 16-bit pieces and add it in multiple
238      // instructions.
239      MachineBasicBlock &MBB = *MI.getParent();
240      DebugLoc DL = II->getDebugLoc();
241      unsigned NewImm = 0;
242      const MipsSEInstrInfo &TII =
243          *static_cast<const MipsSEInstrInfo *>(
244              MBB.getParent()->getSubtarget().getInstrInfo());
245      unsigned Reg = TII.loadImmediate(Offset, MBB, II, DL,
246                                       OffsetBitSize == 16 ? &NewImm : nullptr);
247      BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAdduOp()), Reg).addReg(FrameReg)
248        .addReg(Reg, RegState::Kill);
249
250      FrameReg = Reg;
251      Offset = SignExtend64<16>(NewImm);
252      IsKill = true;
253    }
254  }
255
256  MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill);
257  MI.getOperand(OpNo + 1).ChangeToImmediate(Offset);
258}
259