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