Thumb2InstrInfo.cpp revision 7d8eb70d8d0a68e31d0860c22c227eff56ab6f23
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 if (BaseReg == ARM::SP) { 168 // sub sp, sp, #imm7 169 if (DestReg == ARM::SP && (ThisVal < ((1 << 7)-1) * 4)) { 170 assert((ThisVal & 3) == 0 && "Stack update is not multiple of 4?"); 171 Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; 172 // FIXME: Fix Thumb1 immediate encoding. 173 BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) 174 .addReg(BaseReg).addImm(ThisVal/4); 175 NumBytes = 0; 176 continue; 177 } 178 179 // sub rd, sp, so_imm 180 Opc = isSub ? ARM::t2SUBrSPi : ARM::t2ADDrSPi; 181 if (ARM_AM::getT2SOImmVal(NumBytes) != -1) { 182 NumBytes = 0; 183 } else { 184 // FIXME: Move this to ARMAddressingModes.h? 185 unsigned RotAmt = CountLeadingZeros_32(ThisVal); 186 ThisVal = ThisVal & ARM_AM::rotr32(0xff000000U, RotAmt); 187 NumBytes &= ~ThisVal; 188 assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 && 189 "Bit extraction didn't work?"); 190 } 191 } else { 192 assert(DestReg != ARM::SP && BaseReg != ARM::SP); 193 Opc = isSub ? ARM::t2SUBri : ARM::t2ADDri; 194 if (ARM_AM::getT2SOImmVal(NumBytes) != -1) { 195 NumBytes = 0; 196 } else if (ThisVal < 4096) { 197 Opc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12; 198 NumBytes = 0; 199 } else { 200 // FIXME: Move this to ARMAddressingModes.h? 201 unsigned RotAmt = CountLeadingZeros_32(ThisVal); 202 ThisVal = ThisVal & ARM_AM::rotr32(0xff000000U, RotAmt); 203 NumBytes &= ~ThisVal; 204 assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 && 205 "Bit extraction didn't work?"); 206 } 207 } 208 209 // Build the new ADD / SUB. 210 AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) 211 .addReg(BaseReg, RegState::Kill) 212 .addImm(ThisVal))); 213 214 BaseReg = DestReg; 215 } 216} 217 218static unsigned 219negativeOffsetOpcode(unsigned opcode) 220{ 221 switch (opcode) { 222 case ARM::t2LDRi12: return ARM::t2LDRi8; 223 case ARM::t2LDRHi12: return ARM::t2LDRHi8; 224 case ARM::t2LDRBi12: return ARM::t2LDRBi8; 225 case ARM::t2LDRSHi12: return ARM::t2LDRSHi8; 226 case ARM::t2LDRSBi12: return ARM::t2LDRSBi8; 227 case ARM::t2STRi12: return ARM::t2STRi8; 228 case ARM::t2STRBi12: return ARM::t2STRBi8; 229 case ARM::t2STRHi12: return ARM::t2STRHi8; 230 231 case ARM::t2LDRi8: 232 case ARM::t2LDRHi8: 233 case ARM::t2LDRBi8: 234 case ARM::t2LDRSHi8: 235 case ARM::t2LDRSBi8: 236 case ARM::t2STRi8: 237 case ARM::t2STRBi8: 238 case ARM::t2STRHi8: 239 return opcode; 240 241 default: 242 break; 243 } 244 245 return 0; 246} 247 248static unsigned 249positiveOffsetOpcode(unsigned opcode) 250{ 251 switch (opcode) { 252 case ARM::t2LDRi8: return ARM::t2LDRi12; 253 case ARM::t2LDRHi8: return ARM::t2LDRHi12; 254 case ARM::t2LDRBi8: return ARM::t2LDRBi12; 255 case ARM::t2LDRSHi8: return ARM::t2LDRSHi12; 256 case ARM::t2LDRSBi8: return ARM::t2LDRSBi12; 257 case ARM::t2STRi8: return ARM::t2STRi12; 258 case ARM::t2STRBi8: return ARM::t2STRBi12; 259 case ARM::t2STRHi8: return ARM::t2STRHi12; 260 261 case ARM::t2LDRi12: 262 case ARM::t2LDRHi12: 263 case ARM::t2LDRBi12: 264 case ARM::t2LDRSHi12: 265 case ARM::t2LDRSBi12: 266 case ARM::t2STRi12: 267 case ARM::t2STRBi12: 268 case ARM::t2STRHi12: 269 return opcode; 270 271 default: 272 break; 273 } 274 275 return 0; 276} 277 278static unsigned 279immediateOffsetOpcode(unsigned opcode) 280{ 281 switch (opcode) { 282 case ARM::t2LDRs: return ARM::t2LDRi12; 283 case ARM::t2LDRHs: return ARM::t2LDRHi12; 284 case ARM::t2LDRBs: return ARM::t2LDRBi12; 285 case ARM::t2LDRSHs: return ARM::t2LDRSHi12; 286 case ARM::t2LDRSBs: return ARM::t2LDRSBi12; 287 case ARM::t2STRs: return ARM::t2STRi12; 288 case ARM::t2STRBs: return ARM::t2STRBi12; 289 case ARM::t2STRHs: return ARM::t2STRHi12; 290 291 case ARM::t2LDRi12: 292 case ARM::t2LDRHi12: 293 case ARM::t2LDRBi12: 294 case ARM::t2LDRSHi12: 295 case ARM::t2LDRSBi12: 296 case ARM::t2STRi12: 297 case ARM::t2STRBi12: 298 case ARM::t2STRHi12: 299 case ARM::t2LDRi8: 300 case ARM::t2LDRHi8: 301 case ARM::t2LDRBi8: 302 case ARM::t2LDRSHi8: 303 case ARM::t2LDRSBi8: 304 case ARM::t2STRi8: 305 case ARM::t2STRBi8: 306 case ARM::t2STRHi8: 307 return opcode; 308 309 default: 310 break; 311 } 312 313 return 0; 314} 315 316bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, 317 unsigned FrameReg, int &Offset, 318 const ARMBaseInstrInfo &TII) { 319 unsigned Opcode = MI.getOpcode(); 320 const TargetInstrDesc &Desc = MI.getDesc(); 321 unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); 322 bool isSub = false; 323 324 // Memory operands in inline assembly always use AddrModeT2_i12. 325 if (Opcode == ARM::INLINEASM) 326 AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2? 327 328 if (Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) { 329 Offset += MI.getOperand(FrameRegIdx+1).getImm(); 330 331 bool isSP = FrameReg == ARM::SP; 332 unsigned PredReg; 333 if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) { 334 // Turn it into a move. 335 MI.setDesc(TII.get(ARM::tMOVgpr2gpr)); 336 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 337 // Remove offset and remaining explicit predicate operands. 338 do MI.RemoveOperand(FrameRegIdx+1); 339 while (MI.getNumOperands() > FrameRegIdx+1 && 340 (!MI.getOperand(FrameRegIdx+1).isReg() || 341 !MI.getOperand(FrameRegIdx+1).isImm())); 342 return true; 343 } 344 345 if (Offset < 0) { 346 Offset = -Offset; 347 isSub = true; 348 MI.setDesc(TII.get(isSP ? ARM::t2SUBrSPi : ARM::t2SUBri)); 349 } else { 350 MI.setDesc(TII.get(isSP ? ARM::t2ADDrSPi : ARM::t2ADDri)); 351 } 352 353 // Common case: small offset, fits into instruction. 354 if (ARM_AM::getT2SOImmVal(Offset) != -1) { 355 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 356 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); 357 Offset = 0; 358 return true; 359 } 360 // Another common case: imm12. 361 if (Offset < 4096) { 362 unsigned NewOpc = isSP 363 ? (isSub ? ARM::t2SUBrSPi12 : ARM::t2ADDrSPi12) 364 : (isSub ? ARM::t2SUBri12 : ARM::t2ADDri12); 365 MI.setDesc(TII.get(NewOpc)); 366 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 367 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); 368 Offset = 0; 369 return true; 370 } 371 372 // Otherwise, extract 8 adjacent bits from the immediate into this 373 // t2ADDri/t2SUBri. 374 unsigned RotAmt = CountLeadingZeros_32(Offset); 375 unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xff000000U, RotAmt); 376 377 // We will handle these bits from offset, clear them. 378 Offset &= ~ThisImmVal; 379 380 assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 && 381 "Bit extraction didn't work?"); 382 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal); 383 } else { 384 385 // AddrMode4 cannot handle any offset. 386 if (AddrMode == ARMII::AddrMode4) 387 return false; 388 389 // AddrModeT2_so cannot handle any offset. If there is no offset 390 // register then we change to an immediate version. 391 unsigned NewOpc = Opcode; 392 if (AddrMode == ARMII::AddrModeT2_so) { 393 unsigned OffsetReg = MI.getOperand(FrameRegIdx+1).getReg(); 394 if (OffsetReg != 0) { 395 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 396 return Offset == 0; 397 } 398 399 MI.RemoveOperand(FrameRegIdx+1); 400 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0); 401 NewOpc = immediateOffsetOpcode(Opcode); 402 AddrMode = ARMII::AddrModeT2_i12; 403 } 404 405 unsigned NumBits = 0; 406 unsigned Scale = 1; 407 if (AddrMode == ARMII::AddrModeT2_i8 || AddrMode == ARMII::AddrModeT2_i12) { 408 // i8 supports only negative, and i12 supports only positive, so 409 // based on Offset sign convert Opcode to the appropriate 410 // instruction 411 Offset += MI.getOperand(FrameRegIdx+1).getImm(); 412 if (Offset < 0) { 413 NewOpc = negativeOffsetOpcode(Opcode); 414 NumBits = 8; 415 isSub = true; 416 Offset = -Offset; 417 } else { 418 NewOpc = positiveOffsetOpcode(Opcode); 419 NumBits = 12; 420 } 421 } else { 422 // VFP and NEON address modes. 423 int InstrOffs = 0; 424 if (AddrMode == ARMII::AddrMode5) { 425 const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1); 426 InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm()); 427 if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub) 428 InstrOffs *= -1; 429 } 430 NumBits = 8; 431 Scale = 4; 432 Offset += InstrOffs * 4; 433 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); 434 if (Offset < 0) { 435 Offset = -Offset; 436 isSub = true; 437 } 438 } 439 440 if (NewOpc != Opcode) 441 MI.setDesc(TII.get(NewOpc)); 442 443 MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1); 444 445 // Attempt to fold address computation 446 // Common case: small offset, fits into instruction. 447 int ImmedOffset = Offset / Scale; 448 unsigned Mask = (1 << NumBits) - 1; 449 if ((unsigned)Offset <= Mask * Scale) { 450 // Replace the FrameIndex with fp/sp 451 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 452 if (isSub) { 453 if (AddrMode == ARMII::AddrMode5) 454 // FIXME: Not consistent. 455 ImmedOffset |= 1 << NumBits; 456 else 457 ImmedOffset = -ImmedOffset; 458 } 459 ImmOp.ChangeToImmediate(ImmedOffset); 460 Offset = 0; 461 return true; 462 } 463 464 // Otherwise, offset doesn't fit. Pull in what we can to simplify 465 ImmedOffset = ImmedOffset & Mask; 466 if (isSub) { 467 if (AddrMode == ARMII::AddrMode5) 468 // FIXME: Not consistent. 469 ImmedOffset |= 1 << NumBits; 470 else { 471 ImmedOffset = -ImmedOffset; 472 if (ImmedOffset == 0) 473 // Change the opcode back if the encoded offset is zero. 474 MI.setDesc(TII.get(positiveOffsetOpcode(NewOpc))); 475 } 476 } 477 ImmOp.ChangeToImmediate(ImmedOffset); 478 Offset &= ~(Mask*Scale); 479 } 480 481 Offset = (isSub) ? -Offset : Offset; 482 return Offset == 0; 483} 484