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