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