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 case Mips::LL_MMR6: 102 case Mips::SC_MMR6: 103 return 9; 104 case Mips::INLINEASM: { 105 unsigned ConstraintID = InlineAsm::getMemoryConstraintID(MO.getImm()); 106 switch (ConstraintID) { 107 case InlineAsm::Constraint_ZC: { 108 const MipsSubtarget &Subtarget = MO.getParent() 109 ->getParent() 110 ->getParent() 111 ->getSubtarget<MipsSubtarget>(); 112 if (Subtarget.inMicroMipsMode()) 113 return 12; 114 115 if (Subtarget.hasMips32r6()) 116 return 9; 117 118 return 16; 119 } 120 default: 121 return 16; 122 } 123 } 124 default: 125 return 16; 126 } 127 } 128 129 /// Get the scale factor applied to the immediate in the given load/store. 130 static inline unsigned getLoadStoreOffsetAlign(const unsigned Opcode) { 131 switch (Opcode) { 132 case Mips::LD_H: 133 case Mips::ST_H: 134 return 2; 135 case Mips::LD_W: 136 case Mips::ST_W: 137 return 4; 138 case Mips::LD_D: 139 case Mips::ST_D: 140 return 8; 141 default: 142 return 1; 143 } 144 } 145 146 void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, 147 unsigned OpNo, int FrameIndex, 148 uint64_t StackSize, 149 int64_t SPOffset) const { 150 MachineInstr &MI = *II; 151 MachineFunction &MF = *MI.getParent()->getParent(); 152 MachineFrameInfo &MFI = MF.getFrameInfo(); 153 MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); 154 155 MipsABIInfo ABI = 156 static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI(); 157 const MipsRegisterInfo *RegInfo = 158 static_cast<const MipsRegisterInfo *>(MF.getSubtarget().getRegisterInfo()); 159 160 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 161 int MinCSFI = 0; 162 int MaxCSFI = -1; 163 164 if (CSI.size()) { 165 MinCSFI = CSI[0].getFrameIdx(); 166 MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); 167 } 168 169 bool EhDataRegFI = MipsFI->isEhDataRegFI(FrameIndex); 170 bool IsISRRegFI = MipsFI->isISRRegFI(FrameIndex); 171 // The following stack frame objects are always referenced relative to $sp: 172 // 1. Outgoing arguments. 173 // 2. Pointer to dynamically allocated stack space. 174 // 3. Locations for callee-saved registers. 175 // 4. Locations for eh data registers. 176 // 5. Locations for ISR saved Coprocessor 0 registers 12 & 14. 177 // Everything else is referenced relative to whatever register 178 // getFrameRegister() returns. 179 unsigned FrameReg; 180 181 if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) || EhDataRegFI || 182 IsISRRegFI) 183 FrameReg = ABI.GetStackPtr(); 184 else if (RegInfo->needsStackRealignment(MF)) { 185 if (MFI.hasVarSizedObjects() && !MFI.isFixedObjectIndex(FrameIndex)) 186 FrameReg = ABI.GetBasePtr(); 187 else if (MFI.isFixedObjectIndex(FrameIndex)) 188 FrameReg = getFrameRegister(MF); 189 else 190 FrameReg = ABI.GetStackPtr(); 191 } else 192 FrameReg = getFrameRegister(MF); 193 194 // Calculate final offset. 195 // - There is no need to change the offset if the frame object is one of the 196 // following: an outgoing argument, pointer to a dynamically allocated 197 // stack space or a $gp restore location, 198 // - If the frame object is any of the following, its offset must be adjusted 199 // by adding the size of the stack: 200 // incoming argument, callee-saved register location or local variable. 201 bool IsKill = false; 202 int64_t Offset; 203 204 Offset = SPOffset + (int64_t)StackSize; 205 Offset += MI.getOperand(OpNo + 1).getImm(); 206 207 LLVM_DEBUG(errs() << "Offset : " << Offset << "\n" 208 << "<--------->\n"); 209 210 if (!MI.isDebugValue()) { 211 // Make sure Offset fits within the field available. 212 // For MSA instructions, this is a 10-bit signed immediate (scaled by 213 // element size), otherwise it is a 16-bit signed immediate. 214 unsigned OffsetBitSize = 215 getLoadStoreOffsetSizeInBits(MI.getOpcode(), MI.getOperand(OpNo - 1)); 216 unsigned OffsetAlign = getLoadStoreOffsetAlign(MI.getOpcode()); 217 218 if (OffsetBitSize < 16 && isInt<16>(Offset) && 219 (!isIntN(OffsetBitSize, Offset) || 220 OffsetToAlignment(Offset, OffsetAlign) != 0)) { 221 // If we have an offset that needs to fit into a signed n-bit immediate 222 // (where n < 16) and doesn't, but does fit into 16-bits then use an ADDiu 223 MachineBasicBlock &MBB = *MI.getParent(); 224 DebugLoc DL = II->getDebugLoc(); 225 const TargetRegisterClass *PtrRC = 226 ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; 227 MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); 228 unsigned Reg = RegInfo.createVirtualRegister(PtrRC); 229 const MipsSEInstrInfo &TII = 230 *static_cast<const MipsSEInstrInfo *>( 231 MBB.getParent()->getSubtarget().getInstrInfo()); 232 BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAddiuOp()), Reg) 233 .addReg(FrameReg) 234 .addImm(Offset); 235 236 FrameReg = Reg; 237 Offset = 0; 238 IsKill = true; 239 } else if (!isInt<16>(Offset)) { 240 // Otherwise split the offset into 16-bit pieces and add it in multiple 241 // instructions. 242 MachineBasicBlock &MBB = *MI.getParent(); 243 DebugLoc DL = II->getDebugLoc(); 244 unsigned NewImm = 0; 245 const MipsSEInstrInfo &TII = 246 *static_cast<const MipsSEInstrInfo *>( 247 MBB.getParent()->getSubtarget().getInstrInfo()); 248 unsigned Reg = TII.loadImmediate(Offset, MBB, II, DL, 249 OffsetBitSize == 16 ? &NewImm : nullptr); 250 BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAdduOp()), Reg).addReg(FrameReg) 251 .addReg(Reg, RegState::Kill); 252 253 FrameReg = Reg; 254 Offset = SignExtend64<16>(NewImm); 255 IsKill = true; 256 } 257 } 258 259 MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill); 260 MI.getOperand(OpNo + 1).ChangeToImmediate(Offset); 261 } 262