1 //===- XCoreRegisterInfo.cpp - XCore Register Information -------*- C++ -*-===// 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 XCore implementation of the MRegisterInfo class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "XCoreRegisterInfo.h" 15 #include "XCoreMachineFunctionInfo.h" 16 #include "XCore.h" 17 #include "llvm/CodeGen/MachineInstrBuilder.h" 18 #include "llvm/CodeGen/MachineFunction.h" 19 #include "llvm/CodeGen/MachineFrameInfo.h" 20 #include "llvm/CodeGen/MachineLocation.h" 21 #include "llvm/CodeGen/MachineModuleInfo.h" 22 #include "llvm/CodeGen/MachineRegisterInfo.h" 23 #include "llvm/CodeGen/RegisterScavenging.h" 24 #include "llvm/Target/TargetFrameLowering.h" 25 #include "llvm/Target/TargetMachine.h" 26 #include "llvm/Target/TargetOptions.h" 27 #include "llvm/Target/TargetInstrInfo.h" 28 #include "llvm/Type.h" 29 #include "llvm/Function.h" 30 #include "llvm/ADT/BitVector.h" 31 #include "llvm/ADT/STLExtras.h" 32 #include "llvm/Support/Debug.h" 33 #include "llvm/Support/ErrorHandling.h" 34 #include "llvm/Support/raw_ostream.h" 35 36 #define GET_REGINFO_MC_DESC 37 #define GET_REGINFO_TARGET_DESC 38 #include "XCoreGenRegisterInfo.inc" 39 40 using namespace llvm; 41 42 XCoreRegisterInfo::XCoreRegisterInfo(const TargetInstrInfo &tii) 43 : XCoreGenRegisterInfo(), TII(tii) { 44 } 45 46 // helper functions 47 static inline bool isImmUs(unsigned val) { 48 return val <= 11; 49 } 50 51 static inline bool isImmU6(unsigned val) { 52 return val < (1 << 6); 53 } 54 55 static inline bool isImmU16(unsigned val) { 56 return val < (1 << 16); 57 } 58 59 static const unsigned XCore_ArgRegs[] = { 60 XCore::R0, XCore::R1, XCore::R2, XCore::R3 61 }; 62 63 const unsigned * XCoreRegisterInfo::getArgRegs(const MachineFunction *MF) 64 { 65 return XCore_ArgRegs; 66 } 67 68 unsigned XCoreRegisterInfo::getNumArgRegs(const MachineFunction *MF) 69 { 70 return array_lengthof(XCore_ArgRegs); 71 } 72 73 bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) { 74 return MF.getMMI().hasDebugInfo() || 75 MF.getFunction()->needsUnwindTableEntry(); 76 } 77 78 const unsigned* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) 79 const { 80 static const unsigned CalleeSavedRegs[] = { 81 XCore::R4, XCore::R5, XCore::R6, XCore::R7, 82 XCore::R8, XCore::R9, XCore::R10, XCore::LR, 83 0 84 }; 85 return CalleeSavedRegs; 86 } 87 88 BitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 89 BitVector Reserved(getNumRegs()); 90 const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 91 92 Reserved.set(XCore::CP); 93 Reserved.set(XCore::DP); 94 Reserved.set(XCore::SP); 95 Reserved.set(XCore::LR); 96 if (TFI->hasFP(MF)) { 97 Reserved.set(XCore::R10); 98 } 99 return Reserved; 100 } 101 102 bool 103 XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const { 104 const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 105 106 // TODO can we estimate stack size? 107 return TFI->hasFP(MF); 108 } 109 110 bool 111 XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const { 112 return false; 113 } 114 115 // This function eliminates ADJCALLSTACKDOWN, 116 // ADJCALLSTACKUP pseudo instructions 117 void XCoreRegisterInfo:: 118 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 119 MachineBasicBlock::iterator I) const { 120 const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 121 122 if (!TFI->hasReservedCallFrame(MF)) { 123 // Turn the adjcallstackdown instruction into 'extsp <amt>' and the 124 // adjcallstackup instruction into 'ldaw sp, sp[<amt>]' 125 MachineInstr *Old = I; 126 uint64_t Amount = Old->getOperand(0).getImm(); 127 if (Amount != 0) { 128 // We need to keep the stack aligned properly. To do this, we round the 129 // amount of space needed for the outgoing arguments up to the next 130 // alignment boundary. 131 unsigned Align = TFI->getStackAlignment(); 132 Amount = (Amount+Align-1)/Align*Align; 133 134 assert(Amount%4 == 0); 135 Amount /= 4; 136 137 bool isU6 = isImmU6(Amount); 138 if (!isU6 && !isImmU16(Amount)) { 139 // FIX could emit multiple instructions in this case. 140 #ifndef NDEBUG 141 errs() << "eliminateCallFramePseudoInstr size too big: " 142 << Amount << "\n"; 143 #endif 144 llvm_unreachable(0); 145 } 146 147 MachineInstr *New; 148 if (Old->getOpcode() == XCore::ADJCALLSTACKDOWN) { 149 int Opcode = isU6 ? XCore::EXTSP_u6 : XCore::EXTSP_lu6; 150 New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode)) 151 .addImm(Amount); 152 } else { 153 assert(Old->getOpcode() == XCore::ADJCALLSTACKUP); 154 int Opcode = isU6 ? XCore::LDAWSP_ru6_RRegs : XCore::LDAWSP_lru6_RRegs; 155 New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode), XCore::SP) 156 .addImm(Amount); 157 } 158 159 // Replace the pseudo instruction with a new instruction... 160 MBB.insert(I, New); 161 } 162 } 163 164 MBB.erase(I); 165 } 166 167 void 168 XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 169 int SPAdj, RegScavenger *RS) const { 170 assert(SPAdj == 0 && "Unexpected"); 171 MachineInstr &MI = *II; 172 DebugLoc dl = MI.getDebugLoc(); 173 unsigned i = 0; 174 175 while (!MI.getOperand(i).isFI()) { 176 ++i; 177 assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 178 } 179 180 MachineOperand &FrameOp = MI.getOperand(i); 181 int FrameIndex = FrameOp.getIndex(); 182 183 MachineFunction &MF = *MI.getParent()->getParent(); 184 const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 185 int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex); 186 int StackSize = MF.getFrameInfo()->getStackSize(); 187 188 #ifndef NDEBUG 189 DEBUG(errs() << "\nFunction : " 190 << MF.getFunction()->getName() << "\n"); 191 DEBUG(errs() << "<--------->\n"); 192 DEBUG(MI.print(errs())); 193 DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n"); 194 DEBUG(errs() << "FrameOffset : " << Offset << "\n"); 195 DEBUG(errs() << "StackSize : " << StackSize << "\n"); 196 #endif 197 198 Offset += StackSize; 199 200 // fold constant into offset. 201 Offset += MI.getOperand(i + 1).getImm(); 202 MI.getOperand(i + 1).ChangeToImmediate(0); 203 204 assert(Offset%4 == 0 && "Misaligned stack offset"); 205 206 DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); 207 208 Offset/=4; 209 210 bool FP = TFI->hasFP(MF); 211 212 unsigned Reg = MI.getOperand(0).getReg(); 213 bool isKill = MI.getOpcode() == XCore::STWFI && MI.getOperand(0).isKill(); 214 215 assert(XCore::GRRegsRegisterClass->contains(Reg) && 216 "Unexpected register operand"); 217 218 MachineBasicBlock &MBB = *MI.getParent(); 219 220 if (FP) { 221 bool isUs = isImmUs(Offset); 222 unsigned FramePtr = XCore::R10; 223 224 if (!isUs) { 225 if (!RS) 226 report_fatal_error("eliminateFrameIndex Frame size too big: " + 227 Twine(Offset)); 228 unsigned ScratchReg = RS->scavengeRegister(XCore::GRRegsRegisterClass, II, 229 SPAdj); 230 loadConstant(MBB, II, ScratchReg, Offset, dl); 231 switch (MI.getOpcode()) { 232 case XCore::LDWFI: 233 BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg) 234 .addReg(FramePtr) 235 .addReg(ScratchReg, RegState::Kill); 236 break; 237 case XCore::STWFI: 238 BuildMI(MBB, II, dl, TII.get(XCore::STW_3r)) 239 .addReg(Reg, getKillRegState(isKill)) 240 .addReg(FramePtr) 241 .addReg(ScratchReg, RegState::Kill); 242 break; 243 case XCore::LDAWFI: 244 BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg) 245 .addReg(FramePtr) 246 .addReg(ScratchReg, RegState::Kill); 247 break; 248 default: 249 llvm_unreachable("Unexpected Opcode"); 250 } 251 } else { 252 switch (MI.getOpcode()) { 253 case XCore::LDWFI: 254 BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg) 255 .addReg(FramePtr) 256 .addImm(Offset); 257 break; 258 case XCore::STWFI: 259 BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus)) 260 .addReg(Reg, getKillRegState(isKill)) 261 .addReg(FramePtr) 262 .addImm(Offset); 263 break; 264 case XCore::LDAWFI: 265 BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg) 266 .addReg(FramePtr) 267 .addImm(Offset); 268 break; 269 default: 270 llvm_unreachable("Unexpected Opcode"); 271 } 272 } 273 } else { 274 bool isU6 = isImmU6(Offset); 275 if (!isU6 && !isImmU16(Offset)) 276 report_fatal_error("eliminateFrameIndex Frame size too big: " + 277 Twine(Offset)); 278 279 switch (MI.getOpcode()) { 280 int NewOpcode; 281 case XCore::LDWFI: 282 NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6; 283 BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg) 284 .addImm(Offset); 285 break; 286 case XCore::STWFI: 287 NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6; 288 BuildMI(MBB, II, dl, TII.get(NewOpcode)) 289 .addReg(Reg, getKillRegState(isKill)) 290 .addImm(Offset); 291 break; 292 case XCore::LDAWFI: 293 NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6; 294 BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg) 295 .addImm(Offset); 296 break; 297 default: 298 llvm_unreachable("Unexpected Opcode"); 299 } 300 } 301 // Erase old instruction. 302 MBB.erase(II); 303 } 304 305 void XCoreRegisterInfo:: 306 loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, 307 unsigned DstReg, int64_t Value, DebugLoc dl) const { 308 // TODO use mkmsk if possible. 309 if (!isImmU16(Value)) { 310 // TODO use constant pool. 311 report_fatal_error("loadConstant value too big " + Twine(Value)); 312 } 313 int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6; 314 BuildMI(MBB, I, dl, TII.get(Opcode), DstReg).addImm(Value); 315 } 316 317 int XCoreRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { 318 return XCoreGenRegisterInfo::getDwarfRegNumFull(RegNum, 0); 319 } 320 321 int XCoreRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { 322 return XCoreGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0); 323 } 324 325 unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 326 const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 327 328 return TFI->hasFP(MF) ? XCore::R10 : XCore::SP; 329 } 330 331 unsigned XCoreRegisterInfo::getRARegister() const { 332 return XCore::LR; 333 } 334