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