1 //===- ARMBaseInstrInfo.cpp - ARM 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 Base ARM implementation of the TargetInstrInfo class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "ARMBaseInstrInfo.h" 15 #include "ARM.h" 16 #include "ARMAddressingModes.h" 17 #include "ARMGenInstrInfo.inc" 18 #include "ARMMachineFunctionInfo.h" 19 #include "llvm/ADT/STLExtras.h" 20 #include "llvm/CodeGen/LiveVariables.h" 21 #include "llvm/CodeGen/MachineFrameInfo.h" 22 #include "llvm/CodeGen/MachineInstrBuilder.h" 23 #include "llvm/CodeGen/MachineJumpTableInfo.h" 24 #include "llvm/Target/TargetAsmInfo.h" 25 #include "llvm/Support/CommandLine.h" 26 using namespace llvm; 27 28 static cl::opt<bool> 29 EnableARM3Addr("enable-arm-3-addr-conv", cl::Hidden, 30 cl::desc("Enable ARM 2-addr to 3-addr conv")); 31 32 static inline 33 const MachineInstrBuilder &AddDefaultPred(const MachineInstrBuilder &MIB) { 34 return MIB.addImm((int64_t)ARMCC::AL).addReg(0); 35 } 36 37 static inline 38 const MachineInstrBuilder &AddDefaultCC(const MachineInstrBuilder &MIB) { 39 return MIB.addReg(0); 40 } 41 42 ARMBaseInstrInfo::ARMBaseInstrInfo(const ARMSubtarget &STI) 43 : TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)) { 44 } 45 46 MachineInstr * 47 ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, 48 MachineBasicBlock::iterator &MBBI, 49 LiveVariables *LV) const { 50 if (!EnableARM3Addr) 51 return NULL; 52 53 MachineInstr *MI = MBBI; 54 MachineFunction &MF = *MI->getParent()->getParent(); 55 unsigned TSFlags = MI->getDesc().TSFlags; 56 bool isPre = false; 57 switch ((TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift) { 58 default: return NULL; 59 case ARMII::IndexModePre: 60 isPre = true; 61 break; 62 case ARMII::IndexModePost: 63 break; 64 } 65 66 // Try splitting an indexed load/store to an un-indexed one plus an add/sub 67 // operation. 68 unsigned MemOpc = getUnindexedOpcode(MI->getOpcode()); 69 if (MemOpc == 0) 70 return NULL; 71 72 MachineInstr *UpdateMI = NULL; 73 MachineInstr *MemMI = NULL; 74 unsigned AddrMode = (TSFlags & ARMII::AddrModeMask); 75 const TargetInstrDesc &TID = MI->getDesc(); 76 unsigned NumOps = TID.getNumOperands(); 77 bool isLoad = !TID.mayStore(); 78 const MachineOperand &WB = isLoad ? MI->getOperand(1) : MI->getOperand(0); 79 const MachineOperand &Base = MI->getOperand(2); 80 const MachineOperand &Offset = MI->getOperand(NumOps-3); 81 unsigned WBReg = WB.getReg(); 82 unsigned BaseReg = Base.getReg(); 83 unsigned OffReg = Offset.getReg(); 84 unsigned OffImm = MI->getOperand(NumOps-2).getImm(); 85 ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NumOps-1).getImm(); 86 switch (AddrMode) { 87 default: 88 assert(false && "Unknown indexed op!"); 89 return NULL; 90 case ARMII::AddrMode2: { 91 bool isSub = ARM_AM::getAM2Op(OffImm) == ARM_AM::sub; 92 unsigned Amt = ARM_AM::getAM2Offset(OffImm); 93 if (OffReg == 0) { 94 if (ARM_AM::getSOImmVal(Amt) == -1) 95 // Can't encode it in a so_imm operand. This transformation will 96 // add more than 1 instruction. Abandon! 97 return NULL; 98 UpdateMI = BuildMI(MF, MI->getDebugLoc(), 99 get(isSub ? getOpcode(ARMII::SUBri) : 100 getOpcode(ARMII::ADDri)), WBReg) 101 .addReg(BaseReg).addImm(Amt) 102 .addImm(Pred).addReg(0).addReg(0); 103 } else if (Amt != 0) { 104 ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm); 105 unsigned SOOpc = ARM_AM::getSORegOpc(ShOpc, Amt); 106 UpdateMI = BuildMI(MF, MI->getDebugLoc(), 107 get(isSub ? getOpcode(ARMII::SUBrs) : 108 getOpcode(ARMII::ADDrs)), WBReg) 109 .addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc) 110 .addImm(Pred).addReg(0).addReg(0); 111 } else 112 UpdateMI = BuildMI(MF, MI->getDebugLoc(), 113 get(isSub ? getOpcode(ARMII::SUBrr) : 114 getOpcode(ARMII::ADDrr)), WBReg) 115 .addReg(BaseReg).addReg(OffReg) 116 .addImm(Pred).addReg(0).addReg(0); 117 break; 118 } 119 case ARMII::AddrMode3 : { 120 bool isSub = ARM_AM::getAM3Op(OffImm) == ARM_AM::sub; 121 unsigned Amt = ARM_AM::getAM3Offset(OffImm); 122 if (OffReg == 0) 123 // Immediate is 8-bits. It's guaranteed to fit in a so_imm operand. 124 UpdateMI = BuildMI(MF, MI->getDebugLoc(), 125 get(isSub ? getOpcode(ARMII::SUBri) : 126 getOpcode(ARMII::ADDri)), WBReg) 127 .addReg(BaseReg).addImm(Amt) 128 .addImm(Pred).addReg(0).addReg(0); 129 else 130 UpdateMI = BuildMI(MF, MI->getDebugLoc(), 131 get(isSub ? getOpcode(ARMII::SUBrr) : 132 getOpcode(ARMII::ADDrr)), WBReg) 133 .addReg(BaseReg).addReg(OffReg) 134 .addImm(Pred).addReg(0).addReg(0); 135 break; 136 } 137 } 138 139 std::vector<MachineInstr*> NewMIs; 140 if (isPre) { 141 if (isLoad) 142 MemMI = BuildMI(MF, MI->getDebugLoc(), 143 get(MemOpc), MI->getOperand(0).getReg()) 144 .addReg(WBReg).addReg(0).addImm(0).addImm(Pred); 145 else 146 MemMI = BuildMI(MF, MI->getDebugLoc(), 147 get(MemOpc)).addReg(MI->getOperand(1).getReg()) 148 .addReg(WBReg).addReg(0).addImm(0).addImm(Pred); 149 NewMIs.push_back(MemMI); 150 NewMIs.push_back(UpdateMI); 151 } else { 152 if (isLoad) 153 MemMI = BuildMI(MF, MI->getDebugLoc(), 154 get(MemOpc), MI->getOperand(0).getReg()) 155 .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred); 156 else 157 MemMI = BuildMI(MF, MI->getDebugLoc(), 158 get(MemOpc)).addReg(MI->getOperand(1).getReg()) 159 .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred); 160 if (WB.isDead()) 161 UpdateMI->getOperand(0).setIsDead(); 162 NewMIs.push_back(UpdateMI); 163 NewMIs.push_back(MemMI); 164 } 165 166 // Transfer LiveVariables states, kill / dead info. 167 if (LV) { 168 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 169 MachineOperand &MO = MI->getOperand(i); 170 if (MO.isReg() && MO.getReg() && 171 TargetRegisterInfo::isVirtualRegister(MO.getReg())) { 172 unsigned Reg = MO.getReg(); 173 174 LiveVariables::VarInfo &VI = LV->getVarInfo(Reg); 175 if (MO.isDef()) { 176 MachineInstr *NewMI = (Reg == WBReg) ? UpdateMI : MemMI; 177 if (MO.isDead()) 178 LV->addVirtualRegisterDead(Reg, NewMI); 179 } 180 if (MO.isUse() && MO.isKill()) { 181 for (unsigned j = 0; j < 2; ++j) { 182 // Look at the two new MI's in reverse order. 183 MachineInstr *NewMI = NewMIs[j]; 184 if (!NewMI->readsRegister(Reg)) 185 continue; 186 LV->addVirtualRegisterKilled(Reg, NewMI); 187 if (VI.removeKill(MI)) 188 VI.Kills.push_back(NewMI); 189 break; 190 } 191 } 192 } 193 } 194 } 195 196 MFI->insert(MBBI, NewMIs[1]); 197 MFI->insert(MBBI, NewMIs[0]); 198 return NewMIs[0]; 199 } 200 201 // Branch analysis. 202 bool 203 ARMBaseInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB, 204 MachineBasicBlock *&FBB, 205 SmallVectorImpl<MachineOperand> &Cond, 206 bool AllowModify) const { 207 // If the block has no terminators, it just falls into the block after it. 208 MachineBasicBlock::iterator I = MBB.end(); 209 if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) 210 return false; 211 212 // Get the last instruction in the block. 213 MachineInstr *LastInst = I; 214 215 // If there is only one terminator instruction, process it. 216 unsigned LastOpc = LastInst->getOpcode(); 217 if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { 218 if (LastOpc == getOpcode(ARMII::B)) { 219 TBB = LastInst->getOperand(0).getMBB(); 220 return false; 221 } 222 if (LastOpc == getOpcode(ARMII::Bcc)) { 223 // Block ends with fall-through condbranch. 224 TBB = LastInst->getOperand(0).getMBB(); 225 Cond.push_back(LastInst->getOperand(1)); 226 Cond.push_back(LastInst->getOperand(2)); 227 return false; 228 } 229 return true; // Can't handle indirect branch. 230 } 231 232 // Get the instruction before it if it is a terminator. 233 MachineInstr *SecondLastInst = I; 234 235 // If there are three terminators, we don't know what sort of block this is. 236 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I)) 237 return true; 238 239 // If the block ends with ARMII::B and a ARMII::Bcc, handle it. 240 unsigned SecondLastOpc = SecondLastInst->getOpcode(); 241 if ((SecondLastOpc == getOpcode(ARMII::Bcc)) && 242 (LastOpc == getOpcode(ARMII::B))) { 243 TBB = SecondLastInst->getOperand(0).getMBB(); 244 Cond.push_back(SecondLastInst->getOperand(1)); 245 Cond.push_back(SecondLastInst->getOperand(2)); 246 FBB = LastInst->getOperand(0).getMBB(); 247 return false; 248 } 249 250 // If the block ends with two unconditional branches, handle it. The second 251 // one is not executed, so remove it. 252 if ((SecondLastOpc == getOpcode(ARMII::B)) && 253 (LastOpc == getOpcode(ARMII::B))) { 254 TBB = SecondLastInst->getOperand(0).getMBB(); 255 I = LastInst; 256 if (AllowModify) 257 I->eraseFromParent(); 258 return false; 259 } 260 261 // ...likewise if it ends with a branch table followed by an unconditional 262 // branch. The branch folder can create these, and we must get rid of them for 263 // correctness of Thumb constant islands. 264 if (((SecondLastOpc == getOpcode(ARMII::BR_JTr)) || 265 (SecondLastOpc == getOpcode(ARMII::BR_JTm)) || 266 (SecondLastOpc == getOpcode(ARMII::BR_JTadd))) && 267 (LastOpc == getOpcode(ARMII::B))) { 268 I = LastInst; 269 if (AllowModify) 270 I->eraseFromParent(); 271 return true; 272 } 273 274 // Otherwise, can't handle this. 275 return true; 276 } 277 278 279 unsigned ARMBaseInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { 280 int BOpc = getOpcode(ARMII::B); 281 int BccOpc = getOpcode(ARMII::Bcc); 282 283 MachineBasicBlock::iterator I = MBB.end(); 284 if (I == MBB.begin()) return 0; 285 --I; 286 if (I->getOpcode() != BOpc && I->getOpcode() != BccOpc) 287 return 0; 288 289 // Remove the branch. 290 I->eraseFromParent(); 291 292 I = MBB.end(); 293 294 if (I == MBB.begin()) return 1; 295 --I; 296 if (I->getOpcode() != BccOpc) 297 return 1; 298 299 // Remove the branch. 300 I->eraseFromParent(); 301 return 2; 302 } 303 304 unsigned 305 ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 306 MachineBasicBlock *FBB, 307 const SmallVectorImpl<MachineOperand> &Cond) const { 308 // FIXME this should probably have a DebugLoc argument 309 DebugLoc dl = DebugLoc::getUnknownLoc(); 310 int BOpc = getOpcode(ARMII::B); 311 int BccOpc = getOpcode(ARMII::Bcc); 312 313 // Shouldn't be a fall through. 314 assert(TBB && "InsertBranch must not be told to insert a fallthrough"); 315 assert((Cond.size() == 2 || Cond.size() == 0) && 316 "ARM branch conditions have two components!"); 317 318 if (FBB == 0) { 319 if (Cond.empty()) // Unconditional branch? 320 BuildMI(&MBB, dl, get(BOpc)).addMBB(TBB); 321 else 322 BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB) 323 .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()); 324 return 1; 325 } 326 327 // Two-way conditional branch. 328 BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB) 329 .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()); 330 BuildMI(&MBB, dl, get(BOpc)).addMBB(FBB); 331 return 2; 332 } 333 334 bool ARMBaseInstrInfo:: 335 ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { 336 ARMCC::CondCodes CC = (ARMCC::CondCodes)(int)Cond[0].getImm(); 337 Cond[0].setImm(ARMCC::getOppositeCondition(CC)); 338 return false; 339 } 340 341 bool ARMBaseInstrInfo::isPredicated(const MachineInstr *MI) const { 342 int PIdx = MI->findFirstPredOperandIdx(); 343 return PIdx != -1 && MI->getOperand(PIdx).getImm() != ARMCC::AL; 344 } 345 346 bool ARMBaseInstrInfo:: 347 PredicateInstruction(MachineInstr *MI, 348 const SmallVectorImpl<MachineOperand> &Pred) const { 349 unsigned Opc = MI->getOpcode(); 350 if (Opc == getOpcode(ARMII::B)) { 351 MI->setDesc(get(getOpcode(ARMII::Bcc))); 352 MI->addOperand(MachineOperand::CreateImm(Pred[0].getImm())); 353 MI->addOperand(MachineOperand::CreateReg(Pred[1].getReg(), false)); 354 return true; 355 } 356 357 int PIdx = MI->findFirstPredOperandIdx(); 358 if (PIdx != -1) { 359 MachineOperand &PMO = MI->getOperand(PIdx); 360 PMO.setImm(Pred[0].getImm()); 361 MI->getOperand(PIdx+1).setReg(Pred[1].getReg()); 362 return true; 363 } 364 return false; 365 } 366 367 bool ARMBaseInstrInfo:: 368 SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1, 369 const SmallVectorImpl<MachineOperand> &Pred2) const { 370 if (Pred1.size() > 2 || Pred2.size() > 2) 371 return false; 372 373 ARMCC::CondCodes CC1 = (ARMCC::CondCodes)Pred1[0].getImm(); 374 ARMCC::CondCodes CC2 = (ARMCC::CondCodes)Pred2[0].getImm(); 375 if (CC1 == CC2) 376 return true; 377 378 switch (CC1) { 379 default: 380 return false; 381 case ARMCC::AL: 382 return true; 383 case ARMCC::HS: 384 return CC2 == ARMCC::HI; 385 case ARMCC::LS: 386 return CC2 == ARMCC::LO || CC2 == ARMCC::EQ; 387 case ARMCC::GE: 388 return CC2 == ARMCC::GT; 389 case ARMCC::LE: 390 return CC2 == ARMCC::LT; 391 } 392 } 393 394 bool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI, 395 std::vector<MachineOperand> &Pred) const { 396 const TargetInstrDesc &TID = MI->getDesc(); 397 if (!TID.getImplicitDefs() && !TID.hasOptionalDef()) 398 return false; 399 400 bool Found = false; 401 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 402 const MachineOperand &MO = MI->getOperand(i); 403 if (MO.isReg() && MO.getReg() == ARM::CPSR) { 404 Pred.push_back(MO); 405 Found = true; 406 } 407 } 408 409 return Found; 410 } 411 412 413 /// FIXME: Works around a gcc miscompilation with -fstrict-aliasing 414 static unsigned getNumJTEntries(const std::vector<MachineJumpTableEntry> &JT, 415 unsigned JTI) DISABLE_INLINE; 416 static unsigned getNumJTEntries(const std::vector<MachineJumpTableEntry> &JT, 417 unsigned JTI) { 418 return JT[JTI].MBBs.size(); 419 } 420 421 /// GetInstSize - Return the size of the specified MachineInstr. 422 /// 423 unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { 424 const MachineBasicBlock &MBB = *MI->getParent(); 425 const MachineFunction *MF = MBB.getParent(); 426 const TargetAsmInfo *TAI = MF->getTarget().getTargetAsmInfo(); 427 428 // Basic size info comes from the TSFlags field. 429 const TargetInstrDesc &TID = MI->getDesc(); 430 unsigned TSFlags = TID.TSFlags; 431 432 switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) { 433 default: { 434 // If this machine instr is an inline asm, measure it. 435 if (MI->getOpcode() == ARM::INLINEASM) 436 return TAI->getInlineAsmLength(MI->getOperand(0).getSymbolName()); 437 if (MI->isLabel()) 438 return 0; 439 switch (MI->getOpcode()) { 440 default: 441 assert(0 && "Unknown or unset size field for instr!"); 442 break; 443 case TargetInstrInfo::IMPLICIT_DEF: 444 case TargetInstrInfo::DECLARE: 445 case TargetInstrInfo::DBG_LABEL: 446 case TargetInstrInfo::EH_LABEL: 447 return 0; 448 } 449 break; 450 } 451 case ARMII::Size8Bytes: return 8; // Arm instruction x 2. 452 case ARMII::Size4Bytes: return 4; // Arm instruction. 453 case ARMII::Size2Bytes: return 2; // Thumb instruction. 454 case ARMII::SizeSpecial: { 455 switch (MI->getOpcode()) { 456 case ARM::CONSTPOOL_ENTRY: 457 // If this machine instr is a constant pool entry, its size is recorded as 458 // operand #2. 459 return MI->getOperand(2).getImm(); 460 case ARM::Int_eh_sjlj_setjmp: return 12; 461 case ARM::BR_JTr: 462 case ARM::BR_JTm: 463 case ARM::BR_JTadd: 464 case ARM::t2BR_JTr: 465 case ARM::t2BR_JTm: 466 case ARM::t2BR_JTadd: 467 case ARM::tBR_JTr: { 468 // These are jumptable branches, i.e. a branch followed by an inlined 469 // jumptable. The size is 4 + 4 * number of entries. 470 unsigned NumOps = TID.getNumOperands(); 471 MachineOperand JTOP = 472 MI->getOperand(NumOps - (TID.isPredicable() ? 3 : 2)); 473 unsigned JTI = JTOP.getIndex(); 474 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 475 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 476 assert(JTI < JT.size()); 477 // Thumb instructions are 2 byte aligned, but JT entries are 4 byte 478 // 4 aligned. The assembler / linker may add 2 byte padding just before 479 // the JT entries. The size does not include this padding; the 480 // constant islands pass does separate bookkeeping for it. 481 // FIXME: If we know the size of the function is less than (1 << 16) *2 482 // bytes, we can use 16-bit entries instead. Then there won't be an 483 // alignment issue. 484 return getNumJTEntries(JT, JTI) * 4 + 485 ((MI->getOpcode()==ARM::tBR_JTr) ? 2 : 4); 486 } 487 default: 488 // Otherwise, pseudo-instruction sizes are zero. 489 return 0; 490 } 491 } 492 } 493 return 0; // Not reached 494 } 495 496 /// Return true if the instruction is a register to register move and 497 /// leave the source and dest operands in the passed parameters. 498 /// 499 bool 500 ARMBaseInstrInfo::isMoveInstr(const MachineInstr &MI, 501 unsigned &SrcReg, unsigned &DstReg, 502 unsigned& SrcSubIdx, unsigned& DstSubIdx) const { 503 SrcSubIdx = DstSubIdx = 0; // No sub-registers. 504 505 unsigned oc = MI.getOpcode(); 506 if ((oc == getOpcode(ARMII::FCPYS)) || 507 (oc == getOpcode(ARMII::FCPYD)) || 508 (oc == getOpcode(ARMII::VMOVD)) || 509 (oc == getOpcode(ARMII::VMOVQ))) { 510 SrcReg = MI.getOperand(1).getReg(); 511 DstReg = MI.getOperand(0).getReg(); 512 return true; 513 } 514 else if (oc == getOpcode(ARMII::MOVr)) { 515 assert(MI.getDesc().getNumOperands() >= 2 && 516 MI.getOperand(0).isReg() && 517 MI.getOperand(1).isReg() && 518 "Invalid ARM MOV instruction"); 519 SrcReg = MI.getOperand(1).getReg(); 520 DstReg = MI.getOperand(0).getReg(); 521 return true; 522 } 523 524 return false; 525 } 526 527 unsigned 528 ARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, 529 int &FrameIndex) const { 530 unsigned oc = MI->getOpcode(); 531 if (oc == getOpcode(ARMII::LDR)) { 532 if (MI->getOperand(1).isFI() && 533 MI->getOperand(2).isReg() && 534 MI->getOperand(3).isImm() && 535 MI->getOperand(2).getReg() == 0 && 536 MI->getOperand(3).getImm() == 0) { 537 FrameIndex = MI->getOperand(1).getIndex(); 538 return MI->getOperand(0).getReg(); 539 } 540 } 541 else if ((oc == getOpcode(ARMII::FLDD)) || 542 (oc == getOpcode(ARMII::FLDS))) { 543 if (MI->getOperand(1).isFI() && 544 MI->getOperand(2).isImm() && 545 MI->getOperand(2).getImm() == 0) { 546 FrameIndex = MI->getOperand(1).getIndex(); 547 return MI->getOperand(0).getReg(); 548 } 549 } 550 551 return 0; 552 } 553 554 unsigned 555 ARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI, 556 int &FrameIndex) const { 557 unsigned oc = MI->getOpcode(); 558 if (oc == getOpcode(ARMII::STR)) { 559 if (MI->getOperand(1).isFI() && 560 MI->getOperand(2).isReg() && 561 MI->getOperand(3).isImm() && 562 MI->getOperand(2).getReg() == 0 && 563 MI->getOperand(3).getImm() == 0) { 564 FrameIndex = MI->getOperand(1).getIndex(); 565 return MI->getOperand(0).getReg(); 566 } 567 } 568 else if ((oc == getOpcode(ARMII::FSTD)) || 569 (oc == getOpcode(ARMII::FSTS))) { 570 if (MI->getOperand(1).isFI() && 571 MI->getOperand(2).isImm() && 572 MI->getOperand(2).getImm() == 0) { 573 FrameIndex = MI->getOperand(1).getIndex(); 574 return MI->getOperand(0).getReg(); 575 } 576 } 577 578 return 0; 579 } 580 581 bool 582 ARMBaseInstrInfo::copyRegToReg(MachineBasicBlock &MBB, 583 MachineBasicBlock::iterator I, 584 unsigned DestReg, unsigned SrcReg, 585 const TargetRegisterClass *DestRC, 586 const TargetRegisterClass *SrcRC) const { 587 DebugLoc DL = DebugLoc::getUnknownLoc(); 588 if (I != MBB.end()) DL = I->getDebugLoc(); 589 590 if (DestRC != SrcRC) { 591 // Not yet supported! 592 return false; 593 } 594 595 if (DestRC == ARM::GPRRegisterClass) 596 AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::MOVr)), DestReg) 597 .addReg(SrcReg))); 598 else if (DestRC == ARM::SPRRegisterClass) 599 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::FCPYS)), DestReg) 600 .addReg(SrcReg)); 601 else if (DestRC == ARM::DPRRegisterClass) 602 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::FCPYD)), DestReg) 603 .addReg(SrcReg)); 604 else if (DestRC == ARM::QPRRegisterClass) 605 BuildMI(MBB, I, DL, get(getOpcode(ARMII::VMOVQ)), DestReg).addReg(SrcReg); 606 else 607 return false; 608 609 return true; 610 } 611 612 void ARMBaseInstrInfo:: 613 storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, 614 unsigned SrcReg, bool isKill, int FI, 615 const TargetRegisterClass *RC) const { 616 DebugLoc DL = DebugLoc::getUnknownLoc(); 617 if (I != MBB.end()) DL = I->getDebugLoc(); 618 619 if (RC == ARM::GPRRegisterClass) { 620 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::STR))) 621 .addReg(SrcReg, getKillRegState(isKill)) 622 .addFrameIndex(FI).addReg(0).addImm(0)); 623 } else if (RC == ARM::DPRRegisterClass) { 624 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::FSTD))) 625 .addReg(SrcReg, getKillRegState(isKill)) 626 .addFrameIndex(FI).addImm(0)); 627 } else { 628 assert(RC == ARM::SPRRegisterClass && "Unknown regclass!"); 629 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::FSTS))) 630 .addReg(SrcReg, getKillRegState(isKill)) 631 .addFrameIndex(FI).addImm(0)); 632 } 633 } 634 635 void 636 ARMBaseInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg, 637 bool isKill, 638 SmallVectorImpl<MachineOperand> &Addr, 639 const TargetRegisterClass *RC, 640 SmallVectorImpl<MachineInstr*> &NewMIs) const{ 641 DebugLoc DL = DebugLoc::getUnknownLoc(); 642 unsigned Opc = 0; 643 if (RC == ARM::GPRRegisterClass) { 644 Opc = getOpcode(ARMII::STR); 645 } else if (RC == ARM::DPRRegisterClass) { 646 Opc = getOpcode(ARMII::FSTD); 647 } else { 648 assert(RC == ARM::SPRRegisterClass && "Unknown regclass!"); 649 Opc = getOpcode(ARMII::FSTS); 650 } 651 652 MachineInstrBuilder MIB = 653 BuildMI(MF, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill)); 654 for (unsigned i = 0, e = Addr.size(); i != e; ++i) 655 MIB.addOperand(Addr[i]); 656 AddDefaultPred(MIB); 657 NewMIs.push_back(MIB); 658 return; 659 } 660 661 void ARMBaseInstrInfo:: 662 loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, 663 unsigned DestReg, int FI, 664 const TargetRegisterClass *RC) const { 665 DebugLoc DL = DebugLoc::getUnknownLoc(); 666 if (I != MBB.end()) DL = I->getDebugLoc(); 667 668 if (RC == ARM::GPRRegisterClass) { 669 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::LDR)), DestReg) 670 .addFrameIndex(FI).addReg(0).addImm(0)); 671 } else if (RC == ARM::DPRRegisterClass) { 672 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::FLDD)), DestReg) 673 .addFrameIndex(FI).addImm(0)); 674 } else { 675 assert(RC == ARM::SPRRegisterClass && "Unknown regclass!"); 676 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::FLDS)), DestReg) 677 .addFrameIndex(FI).addImm(0)); 678 } 679 } 680 681 void ARMBaseInstrInfo:: 682 loadRegFromAddr(MachineFunction &MF, unsigned DestReg, 683 SmallVectorImpl<MachineOperand> &Addr, 684 const TargetRegisterClass *RC, 685 SmallVectorImpl<MachineInstr*> &NewMIs) const { 686 DebugLoc DL = DebugLoc::getUnknownLoc(); 687 unsigned Opc = 0; 688 if (RC == ARM::GPRRegisterClass) { 689 Opc = getOpcode(ARMII::LDR); 690 } else if (RC == ARM::DPRRegisterClass) { 691 Opc = getOpcode(ARMII::FLDD); 692 } else { 693 assert(RC == ARM::SPRRegisterClass && "Unknown regclass!"); 694 Opc = getOpcode(ARMII::FLDS); 695 } 696 697 MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg); 698 for (unsigned i = 0, e = Addr.size(); i != e; ++i) 699 MIB.addOperand(Addr[i]); 700 AddDefaultPred(MIB); 701 NewMIs.push_back(MIB); 702 return; 703 } 704 705 MachineInstr *ARMBaseInstrInfo:: 706 foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI, 707 const SmallVectorImpl<unsigned> &Ops, int FI) const { 708 if (Ops.size() != 1) return NULL; 709 710 unsigned OpNum = Ops[0]; 711 unsigned Opc = MI->getOpcode(); 712 MachineInstr *NewMI = NULL; 713 if (Opc == getOpcode(ARMII::MOVr)) { 714 // If it is updating CPSR, then it cannot be folded. 715 if (MI->getOperand(4).getReg() != ARM::CPSR) { 716 unsigned Pred = MI->getOperand(2).getImm(); 717 unsigned PredReg = MI->getOperand(3).getReg(); 718 if (OpNum == 0) { // move -> store 719 unsigned SrcReg = MI->getOperand(1).getReg(); 720 bool isKill = MI->getOperand(1).isKill(); 721 bool isUndef = MI->getOperand(1).isUndef(); 722 NewMI = BuildMI(MF, MI->getDebugLoc(), get(getOpcode(ARMII::STR))) 723 .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef)) 724 .addFrameIndex(FI).addReg(0).addImm(0).addImm(Pred).addReg(PredReg); 725 } else { // move -> load 726 unsigned DstReg = MI->getOperand(0).getReg(); 727 bool isDead = MI->getOperand(0).isDead(); 728 bool isUndef = MI->getOperand(0).isUndef(); 729 NewMI = BuildMI(MF, MI->getDebugLoc(), get(getOpcode(ARMII::LDR))) 730 .addReg(DstReg, 731 RegState::Define | 732 getDeadRegState(isDead) | 733 getUndefRegState(isUndef)) 734 .addFrameIndex(FI).addReg(0).addImm(0).addImm(Pred).addReg(PredReg); 735 } 736 } 737 } 738 else if (Opc == getOpcode(ARMII::FCPYS)) { 739 unsigned Pred = MI->getOperand(2).getImm(); 740 unsigned PredReg = MI->getOperand(3).getReg(); 741 if (OpNum == 0) { // move -> store 742 unsigned SrcReg = MI->getOperand(1).getReg(); 743 bool isKill = MI->getOperand(1).isKill(); 744 bool isUndef = MI->getOperand(1).isUndef(); 745 NewMI = BuildMI(MF, MI->getDebugLoc(), get(getOpcode(ARMII::FSTS))) 746 .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef)) 747 .addFrameIndex(FI) 748 .addImm(0).addImm(Pred).addReg(PredReg); 749 } else { // move -> load 750 unsigned DstReg = MI->getOperand(0).getReg(); 751 bool isDead = MI->getOperand(0).isDead(); 752 bool isUndef = MI->getOperand(0).isUndef(); 753 NewMI = BuildMI(MF, MI->getDebugLoc(), get(getOpcode(ARMII::FLDS))) 754 .addReg(DstReg, 755 RegState::Define | 756 getDeadRegState(isDead) | 757 getUndefRegState(isUndef)) 758 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg); 759 } 760 } 761 else if (Opc == getOpcode(ARMII::FCPYD)) { 762 unsigned Pred = MI->getOperand(2).getImm(); 763 unsigned PredReg = MI->getOperand(3).getReg(); 764 if (OpNum == 0) { // move -> store 765 unsigned SrcReg = MI->getOperand(1).getReg(); 766 bool isKill = MI->getOperand(1).isKill(); 767 bool isUndef = MI->getOperand(1).isUndef(); 768 NewMI = BuildMI(MF, MI->getDebugLoc(), get(getOpcode(ARMII::FSTD))) 769 .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef)) 770 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg); 771 } else { // move -> load 772 unsigned DstReg = MI->getOperand(0).getReg(); 773 bool isDead = MI->getOperand(0).isDead(); 774 bool isUndef = MI->getOperand(0).isUndef(); 775 NewMI = BuildMI(MF, MI->getDebugLoc(), get(getOpcode(ARMII::FLDD))) 776 .addReg(DstReg, 777 RegState::Define | 778 getDeadRegState(isDead) | 779 getUndefRegState(isUndef)) 780 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg); 781 } 782 } 783 784 return NewMI; 785 } 786 787 MachineInstr* 788 ARMBaseInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, 789 MachineInstr* MI, 790 const SmallVectorImpl<unsigned> &Ops, 791 MachineInstr* LoadMI) const { 792 return 0; 793 } 794 795 bool 796 ARMBaseInstrInfo::canFoldMemoryOperand(const MachineInstr *MI, 797 const SmallVectorImpl<unsigned> &Ops) const { 798 if (Ops.size() != 1) return false; 799 800 unsigned Opc = MI->getOpcode(); 801 if (Opc == getOpcode(ARMII::MOVr)) { 802 // If it is updating CPSR, then it cannot be folded. 803 return MI->getOperand(4).getReg() != ARM::CPSR; 804 } 805 else if ((Opc == getOpcode(ARMII::FCPYS)) || 806 (Opc == getOpcode(ARMII::FCPYD))) { 807 return true; 808 } 809 else if ((Opc == getOpcode(ARMII::VMOVD)) || 810 (Opc == getOpcode(ARMII::VMOVQ))) { 811 return false; // FIXME 812 } 813 814 return false; 815 } 816