Thumb1InstrInfo.cpp revision 5ff58b5c3ab6df332600678798ea5c69c5e943d3
1//===- Thumb1InstrInfo.cpp - Thumb-1 Instruction 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 Thumb-1 implementation of the TargetInstrInfo class. 11// 12//===----------------------------------------------------------------------===// 13 14#include "ARMInstrInfo.h" 15#include "ARM.h" 16#include "ARMGenInstrInfo.inc" 17#include "ARMMachineFunctionInfo.h" 18#include "llvm/CodeGen/MachineFrameInfo.h" 19#include "llvm/CodeGen/MachineInstrBuilder.h" 20#include "llvm/ADT/SmallVector.h" 21#include "Thumb1InstrInfo.h" 22 23using namespace llvm; 24 25Thumb1InstrInfo::Thumb1InstrInfo(const ARMSubtarget &STI) 26 : ARMBaseInstrInfo(STI), RI(*this, STI) { 27} 28 29unsigned Thumb1InstrInfo::getUnindexedOpcode(unsigned Opc) const { 30 return 0; 31} 32 33unsigned Thumb1InstrInfo::getOpcode(ARMII::Op Op) const { 34 switch (Op) { 35 case ARMII::ADDri: return ARM::tADDi8; 36 case ARMII::ADDrs: return 0; 37 case ARMII::ADDrr: return ARM::tADDrr; 38 case ARMII::B: return ARM::tB; 39 case ARMII::Bcc: return ARM::tBcc; 40 case ARMII::BR_JTr: return ARM::tBR_JTr; 41 case ARMII::BR_JTm: return 0; 42 case ARMII::BR_JTadd: return 0; 43 case ARMII::BX_RET: return ARM::tBX_RET; 44 case ARMII::FCPYS: return 0; 45 case ARMII::FCPYD: return 0; 46 case ARMII::FLDD: return 0; 47 case ARMII::FLDS: return 0; 48 case ARMII::FSTD: return 0; 49 case ARMII::FSTS: return 0; 50 case ARMII::LDRrr: return ARM::tLDR; 51 case ARMII::LDRri: return 0; 52 case ARMII::MOVr: return ARM::tMOVr; 53 case ARMII::STRrr: return ARM::tSTR; 54 case ARMII::STRri: return 0; 55 case ARMII::SUBri: return ARM::tSUBi8; 56 case ARMII::SUBrs: return 0; 57 case ARMII::SUBrr: return ARM::tSUBrr; 58 case ARMII::VMOVD: return 0; 59 case ARMII::VMOVQ: return 0; 60 default: 61 break; 62 } 63 64 return 0; 65} 66 67bool 68Thumb1InstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const { 69 if (MBB.empty()) return false; 70 71 switch (MBB.back().getOpcode()) { 72 case ARM::tBX_RET: 73 case ARM::tBX_RET_vararg: 74 case ARM::tPOP_RET: 75 case ARM::tB: 76 case ARM::tBR_JTr: 77 return true; 78 default: 79 break; 80 } 81 82 return false; 83} 84 85bool Thumb1InstrInfo::isMoveInstr(const MachineInstr &MI, 86 unsigned &SrcReg, unsigned &DstReg, 87 unsigned& SrcSubIdx, unsigned& DstSubIdx) const { 88 SrcSubIdx = DstSubIdx = 0; // No sub-registers. 89 90 unsigned oc = MI.getOpcode(); 91 switch (oc) { 92 default: 93 return false; 94 case ARM::tMOVr: 95 case ARM::tMOVhir2lor: 96 case ARM::tMOVlor2hir: 97 case ARM::tMOVhir2hir: 98 assert(MI.getDesc().getNumOperands() >= 2 && 99 MI.getOperand(0).isReg() && 100 MI.getOperand(1).isReg() && 101 "Invalid Thumb MOV instruction"); 102 SrcReg = MI.getOperand(1).getReg(); 103 DstReg = MI.getOperand(0).getReg(); 104 return true; 105 } 106} 107 108unsigned Thumb1InstrInfo::isLoadFromStackSlot(const MachineInstr *MI, 109 int &FrameIndex) const { 110 switch (MI->getOpcode()) { 111 default: break; 112 case ARM::tRestore: 113 if (MI->getOperand(1).isFI() && 114 MI->getOperand(2).isImm() && 115 MI->getOperand(2).getImm() == 0) { 116 FrameIndex = MI->getOperand(1).getIndex(); 117 return MI->getOperand(0).getReg(); 118 } 119 break; 120 } 121 return 0; 122} 123 124unsigned Thumb1InstrInfo::isStoreToStackSlot(const MachineInstr *MI, 125 int &FrameIndex) const { 126 switch (MI->getOpcode()) { 127 default: break; 128 case ARM::tSpill: 129 if (MI->getOperand(1).isFI() && 130 MI->getOperand(2).isImm() && 131 MI->getOperand(2).getImm() == 0) { 132 FrameIndex = MI->getOperand(1).getIndex(); 133 return MI->getOperand(0).getReg(); 134 } 135 break; 136 } 137 return 0; 138} 139 140bool Thumb1InstrInfo::copyRegToReg(MachineBasicBlock &MBB, 141 MachineBasicBlock::iterator I, 142 unsigned DestReg, unsigned SrcReg, 143 const TargetRegisterClass *DestRC, 144 const TargetRegisterClass *SrcRC) const { 145 DebugLoc DL = DebugLoc::getUnknownLoc(); 146 if (I != MBB.end()) DL = I->getDebugLoc(); 147 148 if (DestRC == ARM::GPRRegisterClass) { 149 if (SrcRC == ARM::GPRRegisterClass) { 150 BuildMI(MBB, I, DL, get(ARM::tMOVhir2hir), DestReg).addReg(SrcReg); 151 return true; 152 } else if (SrcRC == ARM::tGPRRegisterClass) { 153 BuildMI(MBB, I, DL, get(ARM::tMOVlor2hir), DestReg).addReg(SrcReg); 154 return true; 155 } 156 } else if (DestRC == ARM::tGPRRegisterClass) { 157 if (SrcRC == ARM::GPRRegisterClass) { 158 BuildMI(MBB, I, DL, get(ARM::tMOVhir2lor), DestReg).addReg(SrcReg); 159 return true; 160 } else if (SrcRC == ARM::tGPRRegisterClass) { 161 BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg).addReg(SrcReg); 162 return true; 163 } 164 } 165 166 return false; 167} 168 169bool Thumb1InstrInfo:: 170canFoldMemoryOperand(const MachineInstr *MI, 171 const SmallVectorImpl<unsigned> &Ops) const { 172 if (Ops.size() != 1) return false; 173 174 unsigned OpNum = Ops[0]; 175 unsigned Opc = MI->getOpcode(); 176 switch (Opc) { 177 default: break; 178 case ARM::tMOVr: 179 case ARM::tMOVlor2hir: 180 case ARM::tMOVhir2lor: 181 case ARM::tMOVhir2hir: { 182 if (OpNum == 0) { // move -> store 183 unsigned SrcReg = MI->getOperand(1).getReg(); 184 if (RI.isPhysicalRegister(SrcReg) && !isARMLowRegister(SrcReg)) 185 // tSpill cannot take a high register operand. 186 return false; 187 } else { // move -> load 188 unsigned DstReg = MI->getOperand(0).getReg(); 189 if (RI.isPhysicalRegister(DstReg) && !isARMLowRegister(DstReg)) 190 // tRestore cannot target a high register operand. 191 return false; 192 } 193 return true; 194 } 195 } 196 197 return false; 198} 199 200void Thumb1InstrInfo:: 201storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, 202 unsigned SrcReg, bool isKill, int FI, 203 const TargetRegisterClass *RC) const { 204 DebugLoc DL = DebugLoc::getUnknownLoc(); 205 if (I != MBB.end()) DL = I->getDebugLoc(); 206 207 assert(RC == ARM::tGPRRegisterClass && "Unknown regclass!"); 208 209 if (RC == ARM::tGPRRegisterClass) { 210 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tSpill)) 211 .addReg(SrcReg, getKillRegState(isKill)) 212 .addFrameIndex(FI).addImm(0)); 213 } 214} 215 216void Thumb1InstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg, 217 bool isKill, 218 SmallVectorImpl<MachineOperand> &Addr, 219 const TargetRegisterClass *RC, 220 SmallVectorImpl<MachineInstr*> &NewMIs) const{ 221 DebugLoc DL = DebugLoc::getUnknownLoc(); 222 unsigned Opc = 0; 223 224 assert(RC == ARM::GPRRegisterClass && "Unknown regclass!"); 225 if (RC == ARM::GPRRegisterClass) { 226 Opc = Addr[0].isFI() ? ARM::tSpill : ARM::tSTR; 227 } 228 229 MachineInstrBuilder MIB = 230 BuildMI(MF, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill)); 231 for (unsigned i = 0, e = Addr.size(); i != e; ++i) 232 MIB.addOperand(Addr[i]); 233 AddDefaultPred(MIB); 234 NewMIs.push_back(MIB); 235 return; 236} 237 238void Thumb1InstrInfo:: 239loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, 240 unsigned DestReg, int FI, 241 const TargetRegisterClass *RC) const { 242 DebugLoc DL = DebugLoc::getUnknownLoc(); 243 if (I != MBB.end()) DL = I->getDebugLoc(); 244 245 assert(RC == ARM::tGPRRegisterClass && "Unknown regclass!"); 246 247 if (RC == ARM::tGPRRegisterClass) { 248 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg) 249 .addFrameIndex(FI).addImm(0)); 250 } 251} 252 253void Thumb1InstrInfo:: 254loadRegFromAddr(MachineFunction &MF, unsigned DestReg, 255 SmallVectorImpl<MachineOperand> &Addr, 256 const TargetRegisterClass *RC, 257 SmallVectorImpl<MachineInstr*> &NewMIs) const { 258 DebugLoc DL = DebugLoc::getUnknownLoc(); 259 unsigned Opc = 0; 260 261 if (RC == ARM::GPRRegisterClass) { 262 Opc = Addr[0].isFI() ? ARM::tRestore : ARM::tLDR; 263 } 264 265 MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg); 266 for (unsigned i = 0, e = Addr.size(); i != e; ++i) 267 MIB.addOperand(Addr[i]); 268 AddDefaultPred(MIB); 269 NewMIs.push_back(MIB); 270 return; 271} 272 273bool Thumb1InstrInfo:: 274spillCalleeSavedRegisters(MachineBasicBlock &MBB, 275 MachineBasicBlock::iterator MI, 276 const std::vector<CalleeSavedInfo> &CSI) const { 277 if (CSI.empty()) 278 return false; 279 280 DebugLoc DL = DebugLoc::getUnknownLoc(); 281 if (MI != MBB.end()) DL = MI->getDebugLoc(); 282 283 MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get(ARM::tPUSH)); 284 for (unsigned i = CSI.size(); i != 0; --i) { 285 unsigned Reg = CSI[i-1].getReg(); 286 // Add the callee-saved register as live-in. It's killed at the spill. 287 MBB.addLiveIn(Reg); 288 MIB.addReg(Reg, RegState::Kill); 289 } 290 return true; 291} 292 293bool Thumb1InstrInfo:: 294restoreCalleeSavedRegisters(MachineBasicBlock &MBB, 295 MachineBasicBlock::iterator MI, 296 const std::vector<CalleeSavedInfo> &CSI) const { 297 MachineFunction &MF = *MBB.getParent(); 298 ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 299 if (CSI.empty()) 300 return false; 301 302 bool isVarArg = AFI->getVarArgsRegSaveSize() > 0; 303 MachineInstr *PopMI = MF.CreateMachineInstr(get(ARM::tPOP),MI->getDebugLoc()); 304 for (unsigned i = CSI.size(); i != 0; --i) { 305 unsigned Reg = CSI[i-1].getReg(); 306 if (Reg == ARM::LR) { 307 // Special epilogue for vararg functions. See emitEpilogue 308 if (isVarArg) 309 continue; 310 Reg = ARM::PC; 311 PopMI->setDesc(get(ARM::tPOP_RET)); 312 MI = MBB.erase(MI); 313 } 314 PopMI->addOperand(MachineOperand::CreateReg(Reg, true)); 315 } 316 317 // It's illegal to emit pop instruction without operands. 318 if (PopMI->getNumOperands() > 0) 319 MBB.insert(MI, PopMI); 320 321 return true; 322} 323 324MachineInstr *Thumb1InstrInfo:: 325foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI, 326 const SmallVectorImpl<unsigned> &Ops, int FI) const { 327 if (Ops.size() != 1) return NULL; 328 329 unsigned OpNum = Ops[0]; 330 unsigned Opc = MI->getOpcode(); 331 MachineInstr *NewMI = NULL; 332 switch (Opc) { 333 default: break; 334 case ARM::tMOVr: 335 case ARM::tMOVlor2hir: 336 case ARM::tMOVhir2lor: 337 case ARM::tMOVhir2hir: { 338 if (OpNum == 0) { // move -> store 339 unsigned SrcReg = MI->getOperand(1).getReg(); 340 bool isKill = MI->getOperand(1).isKill(); 341 if (RI.isPhysicalRegister(SrcReg) && !isARMLowRegister(SrcReg)) 342 // tSpill cannot take a high register operand. 343 break; 344 NewMI = AddDefaultPred(BuildMI(MF, MI->getDebugLoc(), get(ARM::tSpill)) 345 .addReg(SrcReg, getKillRegState(isKill)) 346 .addFrameIndex(FI).addImm(0)); 347 } else { // move -> load 348 unsigned DstReg = MI->getOperand(0).getReg(); 349 if (RI.isPhysicalRegister(DstReg) && !isARMLowRegister(DstReg)) 350 // tRestore cannot target a high register operand. 351 break; 352 bool isDead = MI->getOperand(0).isDead(); 353 NewMI = AddDefaultPred(BuildMI(MF, MI->getDebugLoc(), get(ARM::tRestore)) 354 .addReg(DstReg, 355 RegState::Define | getDeadRegState(isDead)) 356 .addFrameIndex(FI).addImm(0)); 357 } 358 break; 359 } 360 } 361 362 return NewMI; 363} 364