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 37 using namespace llvm; 38 39 #define DEBUG_TYPE "mips-reg-info" 40 41 MipsSERegisterInfo::MipsSERegisterInfo() = default; 42 43 bool MipsSERegisterInfo:: 44 requiresRegisterScavenging(const MachineFunction &MF) const { 45 return true; 46 } 47 48 bool MipsSERegisterInfo:: 49 requiresFrameIndexScavenging(const MachineFunction &MF) const { 50 return true; 51 } 52 53 const TargetRegisterClass * 54 MipsSERegisterInfo::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. 65 static 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. 129 static 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 145 void 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->hasStackRealignment(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