Thumb2InstrInfo.cpp revision 5f1fdb3d639bc0300b5a40f1a1c62178fb534668
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 "ARMAddressingModes.h" 17#include "ARMGenInstrInfo.inc" 18#include "ARMMachineFunctionInfo.h" 19#include "llvm/CodeGen/MachineFrameInfo.h" 20#include "llvm/CodeGen/MachineInstrBuilder.h" 21#include "llvm/ADT/SmallVector.h" 22#include "Thumb2InstrInfo.h" 23 24using namespace llvm; 25 26Thumb2InstrInfo::Thumb2InstrInfo(const ARMSubtarget &STI) : RI(*this, STI) { 27} 28 29unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc) const { 30 // FIXME 31 return 0; 32} 33 34bool 35Thumb2InstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const { 36 if (MBB.empty()) return false; 37 38 switch (MBB.back().getOpcode()) { 39 case ARM::t2LDM_RET: 40 case ARM::t2B: // Uncond branch. 41 case ARM::t2BR_JT: // Jumptable branch. 42 case ARM::t2TBB: // Table branch byte. 43 case ARM::t2TBH: // Table branch halfword. 44 case ARM::tBR_JTr: // Jumptable branch (16-bit version). 45 case ARM::tBX_RET: 46 case ARM::tBX_RET_vararg: 47 case ARM::tPOP_RET: 48 case ARM::tB: 49 return true; 50 default: 51 break; 52 } 53 54 return false; 55} 56 57bool 58Thumb2InstrInfo::copyRegToReg(MachineBasicBlock &MBB, 59 MachineBasicBlock::iterator I, 60 unsigned DestReg, unsigned SrcReg, 61 const TargetRegisterClass *DestRC, 62 const TargetRegisterClass *SrcRC) const { 63 DebugLoc DL = DebugLoc::getUnknownLoc(); 64 if (I != MBB.end()) DL = I->getDebugLoc(); 65 66 if (DestRC == ARM::GPRRegisterClass && 67 SrcRC == ARM::GPRRegisterClass) { 68 AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::t2MOVr), 69 DestReg).addReg(SrcReg))); 70 return true; 71 } else if (DestRC == ARM::GPRRegisterClass && 72 SrcRC == ARM::tGPRRegisterClass) { 73 BuildMI(MBB, I, DL, get(ARM::tMOVtgpr2gpr), DestReg).addReg(SrcReg); 74 return true; 75 } else if (DestRC == ARM::tGPRRegisterClass && 76 SrcRC == ARM::GPRRegisterClass) { 77 BuildMI(MBB, I, DL, get(ARM::tMOVgpr2tgpr), DestReg).addReg(SrcReg); 78 return true; 79 } 80 81 // Handle SPR, DPR, and QPR copies. 82 return ARMBaseInstrInfo::copyRegToReg(MBB, I, DestReg, SrcReg, DestRC, SrcRC); 83} 84 85void Thumb2InstrInfo:: 86storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, 87 unsigned SrcReg, bool isKill, int FI, 88 const TargetRegisterClass *RC) const { 89 DebugLoc DL = DebugLoc::getUnknownLoc(); 90 if (I != MBB.end()) DL = I->getDebugLoc(); 91 92 if (RC == ARM::GPRRegisterClass) { 93 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::t2STRi12)) 94 .addReg(SrcReg, getKillRegState(isKill)) 95 .addFrameIndex(FI).addImm(0)); 96 return; 97 } 98 99 ARMBaseInstrInfo::storeRegToStackSlot(MBB, I, SrcReg, isKill, FI, RC); 100} 101 102void Thumb2InstrInfo:: 103loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, 104 unsigned DestReg, int FI, 105 const TargetRegisterClass *RC) const { 106 DebugLoc DL = DebugLoc::getUnknownLoc(); 107 if (I != MBB.end()) DL = I->getDebugLoc(); 108 109 if (RC == ARM::GPRRegisterClass) { 110 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::t2LDRi12), DestReg) 111 .addFrameIndex(FI).addImm(0)); 112 return; 113 } 114 115 ARMBaseInstrInfo::loadRegFromStackSlot(MBB, I, DestReg, FI, RC); 116} 117 118 119void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, 120 MachineBasicBlock::iterator &MBBI, DebugLoc dl, 121 unsigned DestReg, unsigned BaseReg, int NumBytes, 122 ARMCC::CondCodes Pred, unsigned PredReg, 123 const ARMBaseInstrInfo &TII) { 124 bool isSub = NumBytes < 0; 125 if (isSub) NumBytes = -NumBytes; 126 127 // If profitable, use a movw or movt to materialize the offset. 128 // FIXME: Use the scavenger to grab a scratch register. 129 if (DestReg != ARM::SP && DestReg != BaseReg && 130 NumBytes >= 4096 && 131 ARM_AM::getT2SOImmVal(NumBytes) == -1) { 132 bool Fits = false; 133 if (NumBytes < 65536) { 134 // Use a movw to materialize the 16-bit constant. 135 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), DestReg) 136 .addImm(NumBytes) 137 .addImm((unsigned)Pred).addReg(PredReg).addReg(0); 138 Fits = true; 139 } else if ((NumBytes & 0xffff) == 0) { 140 // Use a movt to materialize the 32-bit constant. 141 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVTi16), DestReg) 142 .addReg(DestReg) 143 .addImm(NumBytes >> 16) 144 .addImm((unsigned)Pred).addReg(PredReg).addReg(0); 145 Fits = true; 146 } 147 148 if (Fits) { 149 if (isSub) { 150 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2SUBrr), DestReg) 151 .addReg(BaseReg, RegState::Kill) 152 .addReg(DestReg, RegState::Kill) 153 .addImm((unsigned)Pred).addReg(PredReg).addReg(0); 154 } else { 155 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2ADDrr), DestReg) 156 .addReg(DestReg, RegState::Kill) 157 .addReg(BaseReg, RegState::Kill) 158 .addImm((unsigned)Pred).addReg(PredReg).addReg(0); 159 } 160 return; 161 } 162 } 163 164 while (NumBytes) { 165 unsigned Opc = isSub ? ARM::t2SUBri : ARM::t2ADDri; 166 unsigned ThisVal = NumBytes; 167 if (ARM_AM::getT2SOImmVal(NumBytes) != -1) { 168 NumBytes = 0; 169 } else if (ThisVal < 4096) { 170 Opc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12; 171 NumBytes = 0; 172 } else { 173 // FIXME: Move this to ARMAddressingModes.h? 174 unsigned RotAmt = CountLeadingZeros_32(ThisVal); 175 ThisVal = ThisVal & ARM_AM::rotr32(0xff000000U, RotAmt); 176 NumBytes &= ~ThisVal; 177 assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 && 178 "Bit extraction didn't work?"); 179 } 180 181 // Build the new ADD / SUB. 182 BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) 183 .addReg(BaseReg, RegState::Kill).addImm(ThisVal) 184 .addImm((unsigned)Pred).addReg(PredReg).addReg(0); 185 BaseReg = DestReg; 186 } 187} 188 189static unsigned 190negativeOffsetOpcode(unsigned opcode) 191{ 192 switch (opcode) { 193 case ARM::t2LDRi12: return ARM::t2LDRi8; 194 case ARM::t2LDRHi12: return ARM::t2LDRHi8; 195 case ARM::t2LDRBi12: return ARM::t2LDRBi8; 196 case ARM::t2LDRSHi12: return ARM::t2LDRSHi8; 197 case ARM::t2LDRSBi12: return ARM::t2LDRSBi8; 198 case ARM::t2STRi12: return ARM::t2STRi8; 199 case ARM::t2STRBi12: return ARM::t2STRBi8; 200 case ARM::t2STRHi12: return ARM::t2STRHi8; 201 202 case ARM::t2LDRi8: 203 case ARM::t2LDRHi8: 204 case ARM::t2LDRBi8: 205 case ARM::t2LDRSHi8: 206 case ARM::t2LDRSBi8: 207 case ARM::t2STRi8: 208 case ARM::t2STRBi8: 209 case ARM::t2STRHi8: 210 return opcode; 211 212 default: 213 break; 214 } 215 216 return 0; 217} 218 219static unsigned 220positiveOffsetOpcode(unsigned opcode) 221{ 222 switch (opcode) { 223 case ARM::t2LDRi8: return ARM::t2LDRi12; 224 case ARM::t2LDRHi8: return ARM::t2LDRHi12; 225 case ARM::t2LDRBi8: return ARM::t2LDRBi12; 226 case ARM::t2LDRSHi8: return ARM::t2LDRSHi12; 227 case ARM::t2LDRSBi8: return ARM::t2LDRSBi12; 228 case ARM::t2STRi8: return ARM::t2STRi12; 229 case ARM::t2STRBi8: return ARM::t2STRBi12; 230 case ARM::t2STRHi8: return ARM::t2STRHi12; 231 232 case ARM::t2LDRi12: 233 case ARM::t2LDRHi12: 234 case ARM::t2LDRBi12: 235 case ARM::t2LDRSHi12: 236 case ARM::t2LDRSBi12: 237 case ARM::t2STRi12: 238 case ARM::t2STRBi12: 239 case ARM::t2STRHi12: 240 return opcode; 241 242 default: 243 break; 244 } 245 246 return 0; 247} 248 249static unsigned 250immediateOffsetOpcode(unsigned opcode) 251{ 252 switch (opcode) { 253 case ARM::t2LDRs: return ARM::t2LDRi12; 254 case ARM::t2LDRHs: return ARM::t2LDRHi12; 255 case ARM::t2LDRBs: return ARM::t2LDRBi12; 256 case ARM::t2LDRSHs: return ARM::t2LDRSHi12; 257 case ARM::t2LDRSBs: return ARM::t2LDRSBi12; 258 case ARM::t2STRs: return ARM::t2STRi12; 259 case ARM::t2STRBs: return ARM::t2STRBi12; 260 case ARM::t2STRHs: return ARM::t2STRHi12; 261 262 case ARM::t2LDRi12: 263 case ARM::t2LDRHi12: 264 case ARM::t2LDRBi12: 265 case ARM::t2LDRSHi12: 266 case ARM::t2LDRSBi12: 267 case ARM::t2STRi12: 268 case ARM::t2STRBi12: 269 case ARM::t2STRHi12: 270 case ARM::t2LDRi8: 271 case ARM::t2LDRHi8: 272 case ARM::t2LDRBi8: 273 case ARM::t2LDRSHi8: 274 case ARM::t2LDRSBi8: 275 case ARM::t2STRi8: 276 case ARM::t2STRBi8: 277 case ARM::t2STRHi8: 278 return opcode; 279 280 default: 281 break; 282 } 283 284 return 0; 285} 286 287int llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, 288 unsigned FrameReg, int Offset, 289 const ARMBaseInstrInfo &TII) { 290 unsigned Opcode = MI.getOpcode(); 291 unsigned NewOpc = Opcode; 292 const TargetInstrDesc &Desc = MI.getDesc(); 293 unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); 294 bool isSub = false; 295 296 // Memory operands in inline assembly always use AddrModeT2_i12. 297 if (Opcode == ARM::INLINEASM) 298 AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2? 299 300 if (Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) { 301 Offset += MI.getOperand(FrameRegIdx+1).getImm(); 302 if (Offset == 0) { 303 // Turn it into a move. 304 MI.setDesc(TII.get(ARM::t2MOVr)); 305 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 306 MI.RemoveOperand(FrameRegIdx+1); 307 return 0; 308 } 309 310 if (Offset < 0) { 311 Offset = -Offset; 312 isSub = true; 313 MI.setDesc(TII.get(ARM::t2SUBri)); 314 } 315 316 // Common case: small offset, fits into instruction. 317 if (ARM_AM::getT2SOImmVal(Offset) != -1) { 318 NewOpc = isSub ? ARM::t2SUBri : ARM::t2ADDri; 319 if (NewOpc != Opcode) 320 MI.setDesc(TII.get(NewOpc)); 321 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 322 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); 323 return 0; 324 } 325 // Another common case: imm12. 326 if (Offset < 4096) { 327 NewOpc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12; 328 if (NewOpc != Opcode) 329 MI.setDesc(TII.get(NewOpc)); 330 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 331 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); 332 return 0; 333 } 334 335 // Otherwise, extract 8 adjacent bits from the immediate into this 336 // t2ADDri/t2SUBri. 337 unsigned RotAmt = CountLeadingZeros_32(Offset); 338 unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xff000000U, RotAmt); 339 340 // We will handle these bits from offset, clear them. 341 Offset &= ~ThisImmVal; 342 343 assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 && 344 "Bit extraction didn't work?"); 345 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal); 346 } else { 347 // AddrModeT2_so cannot handle any offset. If there is no offset 348 // register then we change to an immediate version. 349 NewOpc = Opcode; 350 if (AddrMode == ARMII::AddrModeT2_so) { 351 unsigned OffsetReg = MI.getOperand(FrameRegIdx+1).getReg(); 352 if (OffsetReg != 0) { 353 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 354 return Offset; 355 } 356 357 MI.RemoveOperand(FrameRegIdx+1); 358 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0); 359 NewOpc = immediateOffsetOpcode(Opcode); 360 AddrMode = ARMII::AddrModeT2_i12; 361 } 362 363 unsigned NumBits = 0; 364 unsigned Scale = 1; 365 if (AddrMode == ARMII::AddrModeT2_i8 || AddrMode == ARMII::AddrModeT2_i12) { 366 // i8 supports only negative, and i12 supports only positive, so 367 // based on Offset sign convert Opcode to the appropriate 368 // instruction 369 Offset += MI.getOperand(FrameRegIdx+1).getImm(); 370 if (Offset < 0) { 371 NewOpc = negativeOffsetOpcode(Opcode); 372 NumBits = 8; 373 isSub = true; 374 Offset = -Offset; 375 } else { 376 NewOpc = positiveOffsetOpcode(Opcode); 377 NumBits = 12; 378 } 379 } else { 380 // VFP address modes. 381 assert(AddrMode == ARMII::AddrMode5); 382 int InstrOffs=ARM_AM::getAM5Offset(MI.getOperand(FrameRegIdx+1).getImm()); 383 if (ARM_AM::getAM5Op(MI.getOperand(FrameRegIdx+1).getImm()) ==ARM_AM::sub) 384 InstrOffs *= -1; 385 NumBits = 8; 386 Scale = 4; 387 Offset += InstrOffs * 4; 388 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); 389 if (Offset < 0) { 390 Offset = -Offset; 391 isSub = true; 392 } 393 } 394 395 if (NewOpc != Opcode) 396 MI.setDesc(TII.get(NewOpc)); 397 398 MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1); 399 400 // Attempt to fold address computation 401 // Common case: small offset, fits into instruction. 402 int ImmedOffset = Offset / Scale; 403 unsigned Mask = (1 << NumBits) - 1; 404 if ((unsigned)Offset <= Mask * Scale) { 405 // Replace the FrameIndex with fp/sp 406 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 407 if (isSub) { 408 if (AddrMode == ARMII::AddrMode5) 409 // FIXME: Not consistent. 410 ImmedOffset |= 1 << NumBits; 411 else 412 ImmedOffset = -ImmedOffset; 413 } 414 ImmOp.ChangeToImmediate(ImmedOffset); 415 return 0; 416 } 417 418 // Otherwise, offset doesn't fit. Pull in what we can to simplify 419 ImmedOffset = ImmedOffset & Mask; 420 if (isSub) { 421 if (AddrMode == ARMII::AddrMode5) 422 // FIXME: Not consistent. 423 ImmedOffset |= 1 << NumBits; 424 else 425 ImmedOffset = -ImmedOffset; 426 } 427 ImmOp.ChangeToImmediate(ImmedOffset); 428 Offset &= ~(Mask*Scale); 429 } 430 431 return (isSub) ? -Offset : Offset; 432} 433