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