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