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