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