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