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