ARMBaseInstrInfo.cpp revision 202375
1259698Sdim//===- ARMBaseInstrInfo.cpp - ARM Instruction Information -------*- C++ -*-===// 2259698Sdim// 3259698Sdim// The LLVM Compiler Infrastructure 4259698Sdim// 5259698Sdim// This file is distributed under the University of Illinois Open Source 6259698Sdim// License. See LICENSE.TXT for details. 7259698Sdim// 8259698Sdim//===----------------------------------------------------------------------===// 9259698Sdim// 10259698Sdim// This file contains the Base ARM implementation of the TargetInstrInfo class. 11259698Sdim// 12288943Sdim//===----------------------------------------------------------------------===// 13259698Sdim 14280031Sdim#include "ARMBaseInstrInfo.h" 15259698Sdim#include "ARM.h" 16259698Sdim#include "ARMAddressingModes.h" 17259698Sdim#include "ARMConstantPoolValue.h" 18259698Sdim#include "ARMGenInstrInfo.inc" 19276479Sdim#include "ARMMachineFunctionInfo.h" 20288943Sdim#include "ARMRegisterInfo.h" 21288943Sdim#include "llvm/Constants.h" 22259698Sdim#include "llvm/Function.h" 23259698Sdim#include "llvm/GlobalValue.h" 24259698Sdim#include "llvm/ADT/STLExtras.h" 25259698Sdim#include "llvm/CodeGen/LiveVariables.h" 26259698Sdim#include "llvm/CodeGen/MachineConstantPool.h" 27276479Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 28276479Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 29259698Sdim#include "llvm/CodeGen/MachineJumpTableInfo.h" 30259698Sdim#include "llvm/CodeGen/MachineMemOperand.h" 31259698Sdim#include "llvm/CodeGen/PseudoSourceValue.h" 32259698Sdim#include "llvm/MC/MCAsmInfo.h" 33259698Sdim#include "llvm/Support/CommandLine.h" 34259698Sdim#include "llvm/Support/Debug.h" 35259698Sdim#include "llvm/Support/ErrorHandling.h" 36259698Sdimusing namespace llvm; 37259698Sdim 38259698Sdimstatic cl::opt<bool> 39259698SdimEnableARM3Addr("enable-arm-3-addr-conv", cl::Hidden, 40259698Sdim cl::desc("Enable ARM 2-addr to 3-addr conv")); 41259698Sdim 42259698SdimARMBaseInstrInfo::ARMBaseInstrInfo(const ARMSubtarget& STI) 43259698Sdim : TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)), 44259698Sdim Subtarget(STI) { 45259698Sdim} 46259698Sdim 47259698SdimMachineInstr * 48259698SdimARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, 49259698Sdim MachineBasicBlock::iterator &MBBI, 50259698Sdim LiveVariables *LV) const { 51259698Sdim // FIXME: Thumb2 support. 52259698Sdim 53259698Sdim if (!EnableARM3Addr) 54259698Sdim return NULL; 55259698Sdim 56259698Sdim MachineInstr *MI = MBBI; 57259698Sdim MachineFunction &MF = *MI->getParent()->getParent(); 58259698Sdim unsigned TSFlags = MI->getDesc().TSFlags; 59259698Sdim bool isPre = false; 60259698Sdim switch ((TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift) { 61259698Sdim default: return NULL; 62259698Sdim case ARMII::IndexModePre: 63259698Sdim isPre = true; 64259698Sdim break; 65259698Sdim case ARMII::IndexModePost: 66259698Sdim break; 67259698Sdim } 68259698Sdim 69259698Sdim // Try splitting an indexed load/store to an un-indexed one plus an add/sub 70259698Sdim // operation. 71259698Sdim unsigned MemOpc = getUnindexedOpcode(MI->getOpcode()); 72276479Sdim if (MemOpc == 0) 73259698Sdim return NULL; 74259698Sdim 75259698Sdim MachineInstr *UpdateMI = NULL; 76259698Sdim MachineInstr *MemMI = NULL; 77259698Sdim unsigned AddrMode = (TSFlags & ARMII::AddrModeMask); 78259698Sdim const TargetInstrDesc &TID = MI->getDesc(); 79276479Sdim unsigned NumOps = TID.getNumOperands(); 80259698Sdim bool isLoad = !TID.mayStore(); 81259698Sdim const MachineOperand &WB = isLoad ? MI->getOperand(1) : MI->getOperand(0); 82259698Sdim const MachineOperand &Base = MI->getOperand(2); 83259698Sdim const MachineOperand &Offset = MI->getOperand(NumOps-3); 84259698Sdim unsigned WBReg = WB.getReg(); 85259698Sdim unsigned BaseReg = Base.getReg(); 86259698Sdim unsigned OffReg = Offset.getReg(); 87259698Sdim unsigned OffImm = MI->getOperand(NumOps-2).getImm(); 88259698Sdim ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NumOps-1).getImm(); 89259698Sdim switch (AddrMode) { 90259698Sdim default: 91259698Sdim assert(false && "Unknown indexed op!"); 92259698Sdim return NULL; 93259698Sdim case ARMII::AddrMode2: { 94259698Sdim bool isSub = ARM_AM::getAM2Op(OffImm) == ARM_AM::sub; 95259698Sdim unsigned Amt = ARM_AM::getAM2Offset(OffImm); 96259698Sdim if (OffReg == 0) { 97259698Sdim if (ARM_AM::getSOImmVal(Amt) == -1) 98259698Sdim // Can't encode it in a so_imm operand. This transformation will 99259698Sdim // add more than 1 instruction. Abandon! 100259698Sdim return NULL; 101259698Sdim UpdateMI = BuildMI(MF, MI->getDebugLoc(), 102259698Sdim get(isSub ? ARM::SUBri : ARM::ADDri), WBReg) 103259698Sdim .addReg(BaseReg).addImm(Amt) 104259698Sdim .addImm(Pred).addReg(0).addReg(0); 105259698Sdim } else if (Amt != 0) { 106259698Sdim ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm); 107259698Sdim unsigned SOOpc = ARM_AM::getSORegOpc(ShOpc, Amt); 108259698Sdim UpdateMI = BuildMI(MF, MI->getDebugLoc(), 109259698Sdim get(isSub ? ARM::SUBrs : ARM::ADDrs), WBReg) 110259698Sdim .addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc) 111259698Sdim .addImm(Pred).addReg(0).addReg(0); 112259698Sdim } else 113259698Sdim UpdateMI = BuildMI(MF, MI->getDebugLoc(), 114259698Sdim get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg) 115259698Sdim .addReg(BaseReg).addReg(OffReg) 116259698Sdim .addImm(Pred).addReg(0).addReg(0); 117259698Sdim break; 118259698Sdim } 119259698Sdim case ARMII::AddrMode3 : { 120259698Sdim bool isSub = ARM_AM::getAM3Op(OffImm) == ARM_AM::sub; 121259698Sdim unsigned Amt = ARM_AM::getAM3Offset(OffImm); 122259698Sdim if (OffReg == 0) 123259698Sdim // Immediate is 8-bits. It's guaranteed to fit in a so_imm operand. 124259698Sdim UpdateMI = BuildMI(MF, MI->getDebugLoc(), 125259698Sdim get(isSub ? ARM::SUBri : ARM::ADDri), WBReg) 126259698Sdim .addReg(BaseReg).addImm(Amt) 127259698Sdim .addImm(Pred).addReg(0).addReg(0); 128259698Sdim else 129259698Sdim UpdateMI = BuildMI(MF, MI->getDebugLoc(), 130259698Sdim get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg) 131259698Sdim .addReg(BaseReg).addReg(OffReg) 132259698Sdim .addImm(Pred).addReg(0).addReg(0); 133259698Sdim break; 134259698Sdim } 135259698Sdim } 136259698Sdim 137259698Sdim std::vector<MachineInstr*> NewMIs; 138259698Sdim if (isPre) { 139259698Sdim if (isLoad) 140259698Sdim MemMI = BuildMI(MF, MI->getDebugLoc(), 141259698Sdim get(MemOpc), MI->getOperand(0).getReg()) 142259698Sdim .addReg(WBReg).addReg(0).addImm(0).addImm(Pred); 143259698Sdim else 144259698Sdim MemMI = BuildMI(MF, MI->getDebugLoc(), 145259698Sdim get(MemOpc)).addReg(MI->getOperand(1).getReg()) 146259698Sdim .addReg(WBReg).addReg(0).addImm(0).addImm(Pred); 147259698Sdim NewMIs.push_back(MemMI); 148259698Sdim NewMIs.push_back(UpdateMI); 149259698Sdim } else { 150259698Sdim if (isLoad) 151259698Sdim MemMI = BuildMI(MF, MI->getDebugLoc(), 152259698Sdim get(MemOpc), MI->getOperand(0).getReg()) 153259698Sdim .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred); 154259698Sdim else 155259698Sdim MemMI = BuildMI(MF, MI->getDebugLoc(), 156259698Sdim get(MemOpc)).addReg(MI->getOperand(1).getReg()) 157259698Sdim .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred); 158259698Sdim if (WB.isDead()) 159259698Sdim UpdateMI->getOperand(0).setIsDead(); 160259698Sdim NewMIs.push_back(UpdateMI); 161259698Sdim NewMIs.push_back(MemMI); 162259698Sdim } 163259698Sdim 164259698Sdim // Transfer LiveVariables states, kill / dead info. 165259698Sdim if (LV) { 166259698Sdim for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 167259698Sdim MachineOperand &MO = MI->getOperand(i); 168259698Sdim if (MO.isReg() && MO.getReg() && 169259698Sdim TargetRegisterInfo::isVirtualRegister(MO.getReg())) { 170259698Sdim unsigned Reg = MO.getReg(); 171259698Sdim 172259698Sdim LiveVariables::VarInfo &VI = LV->getVarInfo(Reg); 173280031Sdim if (MO.isDef()) { 174259698Sdim MachineInstr *NewMI = (Reg == WBReg) ? UpdateMI : MemMI; 175259698Sdim if (MO.isDead()) 176259698Sdim LV->addVirtualRegisterDead(Reg, NewMI); 177259698Sdim } 178259698Sdim if (MO.isUse() && MO.isKill()) { 179259698Sdim for (unsigned j = 0; j < 2; ++j) { 180259698Sdim // Look at the two new MI's in reverse order. 181259698Sdim MachineInstr *NewMI = NewMIs[j]; 182259698Sdim if (!NewMI->readsRegister(Reg)) 183259698Sdim continue; 184259698Sdim LV->addVirtualRegisterKilled(Reg, NewMI); 185259698Sdim if (VI.removeKill(MI)) 186259698Sdim VI.Kills.push_back(NewMI); 187259698Sdim break; 188259698Sdim } 189259698Sdim } 190259698Sdim } 191259698Sdim } 192259698Sdim } 193259698Sdim 194259698Sdim MFI->insert(MBBI, NewMIs[1]); 195259698Sdim MFI->insert(MBBI, NewMIs[0]); 196259698Sdim return NewMIs[0]; 197259698Sdim} 198259698Sdim 199259698Sdim// Branch analysis. 200259698Sdimbool 201259698SdimARMBaseInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB, 202259698Sdim MachineBasicBlock *&FBB, 203259698Sdim SmallVectorImpl<MachineOperand> &Cond, 204259698Sdim bool AllowModify) const { 205259698Sdim // If the block has no terminators, it just falls into the block after it. 206259698Sdim MachineBasicBlock::iterator I = MBB.end(); 207259698Sdim if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) 208259698Sdim return false; 209259698Sdim 210259698Sdim // Get the last instruction in the block. 211259698Sdim MachineInstr *LastInst = I; 212259698Sdim 213259698Sdim // If there is only one terminator instruction, process it. 214259698Sdim unsigned LastOpc = LastInst->getOpcode(); 215259698Sdim if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { 216259698Sdim if (isUncondBranchOpcode(LastOpc)) { 217259698Sdim TBB = LastInst->getOperand(0).getMBB(); 218259698Sdim return false; 219259698Sdim } 220259698Sdim if (isCondBranchOpcode(LastOpc)) { 221259698Sdim // Block ends with fall-through condbranch. 222259698Sdim TBB = LastInst->getOperand(0).getMBB(); 223259698Sdim Cond.push_back(LastInst->getOperand(1)); 224259698Sdim Cond.push_back(LastInst->getOperand(2)); 225259698Sdim return false; 226259698Sdim } 227259698Sdim return true; // Can't handle indirect branch. 228259698Sdim } 229259698Sdim 230259698Sdim // Get the instruction before it if it is a terminator. 231259698Sdim MachineInstr *SecondLastInst = I; 232259698Sdim 233259698Sdim // If there are three terminators, we don't know what sort of block this is. 234259698Sdim if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I)) 235259698Sdim return true; 236259698Sdim 237259698Sdim // If the block ends with a B and a Bcc, handle it. 238259698Sdim unsigned SecondLastOpc = SecondLastInst->getOpcode(); 239259698Sdim if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) { 240259698Sdim TBB = SecondLastInst->getOperand(0).getMBB(); 241259698Sdim Cond.push_back(SecondLastInst->getOperand(1)); 242259698Sdim Cond.push_back(SecondLastInst->getOperand(2)); 243259698Sdim FBB = LastInst->getOperand(0).getMBB(); 244276479Sdim return false; 245259698Sdim } 246276479Sdim 247259698Sdim // If the block ends with two unconditional branches, handle it. The second 248276479Sdim // one is not executed, so remove it. 249259698Sdim if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) { 250259698Sdim TBB = SecondLastInst->getOperand(0).getMBB(); 251259698Sdim I = LastInst; 252276479Sdim if (AllowModify) 253259698Sdim I->eraseFromParent(); 254276479Sdim return false; 255288943Sdim } 256276479Sdim 257259698Sdim // ...likewise if it ends with a branch table followed by an unconditional 258259698Sdim // branch. The branch folder can create these, and we must get rid of them for 259259698Sdim // correctness of Thumb constant islands. 260259698Sdim if ((isJumpTableBranchOpcode(SecondLastOpc) || 261259698Sdim isIndirectBranchOpcode(SecondLastOpc)) && 262259698Sdim isUncondBranchOpcode(LastOpc)) { 263259698Sdim I = LastInst; 264259698Sdim if (AllowModify) 265259698Sdim I->eraseFromParent(); 266259698Sdim return true; 267259698Sdim } 268276479Sdim 269276479Sdim // Otherwise, can't handle this. 270259698Sdim return true; 271259698Sdim} 272259698Sdim 273259698Sdim 274259698Sdimunsigned ARMBaseInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { 275259698Sdim MachineBasicBlock::iterator I = MBB.end(); 276259698Sdim if (I == MBB.begin()) return 0; 277259698Sdim --I; 278259698Sdim if (!isUncondBranchOpcode(I->getOpcode()) && 279259698Sdim !isCondBranchOpcode(I->getOpcode())) 280259698Sdim return 0; 281259698Sdim 282259698Sdim // Remove the branch. 283259698Sdim I->eraseFromParent(); 284259698Sdim 285259698Sdim I = MBB.end(); 286259698Sdim 287288943Sdim if (I == MBB.begin()) return 1; 288288943Sdim --I; 289288943Sdim if (!isCondBranchOpcode(I->getOpcode())) 290288943Sdim return 1; 291288943Sdim 292288943Sdim // Remove the branch. 293288943Sdim I->eraseFromParent(); 294288943Sdim return 2; 295288943Sdim} 296288943Sdim 297288943Sdimunsigned 298288943SdimARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 299288943Sdim MachineBasicBlock *FBB, 300288943Sdim const SmallVectorImpl<MachineOperand> &Cond) const { 301288943Sdim // FIXME this should probably have a DebugLoc argument 302288943Sdim DebugLoc dl = DebugLoc::getUnknownLoc(); 303288943Sdim 304288943Sdim ARMFunctionInfo *AFI = MBB.getParent()->getInfo<ARMFunctionInfo>(); 305259698Sdim int BOpc = !AFI->isThumbFunction() 306288943Sdim ? ARM::B : (AFI->isThumb2Function() ? ARM::t2B : ARM::tB); 307288943Sdim int BccOpc = !AFI->isThumbFunction() 308288943Sdim ? ARM::Bcc : (AFI->isThumb2Function() ? ARM::t2Bcc : ARM::tBcc); 309288943Sdim 310288943Sdim // Shouldn't be a fall through. 311288943Sdim assert(TBB && "InsertBranch must not be told to insert a fallthrough"); 312288943Sdim assert((Cond.size() == 2 || Cond.size() == 0) && 313288943Sdim "ARM branch conditions have two components!"); 314288943Sdim 315288943Sdim if (FBB == 0) { 316288943Sdim if (Cond.empty()) // Unconditional branch? 317288943Sdim BuildMI(&MBB, dl, get(BOpc)).addMBB(TBB); 318288943Sdim else 319288943Sdim BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB) 320288943Sdim .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()); 321288943Sdim return 1; 322288943Sdim } 323288943Sdim 324288943Sdim // Two-way conditional branch. 325288943Sdim BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB) 326288943Sdim .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()); 327288943Sdim BuildMI(&MBB, dl, get(BOpc)).addMBB(FBB); 328288943Sdim return 2; 329288943Sdim} 330288943Sdim 331288943Sdimbool ARMBaseInstrInfo:: 332288943SdimReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { 333288943Sdim ARMCC::CondCodes CC = (ARMCC::CondCodes)(int)Cond[0].getImm(); 334288943Sdim Cond[0].setImm(ARMCC::getOppositeCondition(CC)); 335288943Sdim return false; 336288943Sdim} 337288943Sdim 338288943Sdimbool ARMBaseInstrInfo:: 339288943SdimPredicateInstruction(MachineInstr *MI, 340288943Sdim const SmallVectorImpl<MachineOperand> &Pred) const { 341288943Sdim unsigned Opc = MI->getOpcode(); 342288943Sdim if (isUncondBranchOpcode(Opc)) { 343288943Sdim MI->setDesc(get(getMatchingCondBranchOpcode(Opc))); 344288943Sdim MI->addOperand(MachineOperand::CreateImm(Pred[0].getImm())); 345288943Sdim MI->addOperand(MachineOperand::CreateReg(Pred[1].getReg(), false)); 346259698Sdim return true; 347259698Sdim } 348259698Sdim 349259698Sdim int PIdx = MI->findFirstPredOperandIdx(); 350259698Sdim if (PIdx != -1) { 351259698Sdim MachineOperand &PMO = MI->getOperand(PIdx); 352259698Sdim PMO.setImm(Pred[0].getImm()); 353259698Sdim MI->getOperand(PIdx+1).setReg(Pred[1].getReg()); 354259698Sdim return true; 355259698Sdim } 356259698Sdim return false; 357259698Sdim} 358259698Sdim 359259698Sdimbool ARMBaseInstrInfo:: 360259698SdimSubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1, 361296417Sdim const SmallVectorImpl<MachineOperand> &Pred2) const { 362296417Sdim if (Pred1.size() > 2 || Pred2.size() > 2) 363259698Sdim return false; 364259698Sdim 365259698Sdim ARMCC::CondCodes CC1 = (ARMCC::CondCodes)Pred1[0].getImm(); 366259698Sdim ARMCC::CondCodes CC2 = (ARMCC::CondCodes)Pred2[0].getImm(); 367259698Sdim if (CC1 == CC2) 368259698Sdim return true; 369259698Sdim 370259698Sdim switch (CC1) { 371259698Sdim default: 372259698Sdim return false; 373259698Sdim case ARMCC::AL: 374259698Sdim return true; 375259698Sdim case ARMCC::HS: 376259698Sdim return CC2 == ARMCC::HI; 377259698Sdim case ARMCC::LS: 378259698Sdim return CC2 == ARMCC::LO || CC2 == ARMCC::EQ; 379259698Sdim case ARMCC::GE: 380259698Sdim return CC2 == ARMCC::GT; 381259698Sdim case ARMCC::LE: 382259698Sdim return CC2 == ARMCC::LT; 383259698Sdim } 384259698Sdim} 385259698Sdim 386276479Sdimbool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI, 387276479Sdim std::vector<MachineOperand> &Pred) const { 388276479Sdim // FIXME: This confuses implicit_def with optional CPSR def. 389276479Sdim const TargetInstrDesc &TID = MI->getDesc(); 390259698Sdim if (!TID.getImplicitDefs() && !TID.hasOptionalDef()) 391259698Sdim return false; 392259698Sdim 393259698Sdim bool Found = false; 394259698Sdim for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 395259698Sdim const MachineOperand &MO = MI->getOperand(i); 396259698Sdim if (MO.isReg() && MO.getReg() == ARM::CPSR) { 397259698Sdim Pred.push_back(MO); 398259698Sdim Found = true; 399259698Sdim } 400259698Sdim } 401259698Sdim 402259698Sdim return Found; 403259698Sdim} 404259698Sdim 405259698Sdim/// isPredicable - Return true if the specified instruction can be predicated. 406259698Sdim/// By default, this returns true for every instruction with a 407259698Sdim/// PredicateOperand. 408259698Sdimbool ARMBaseInstrInfo::isPredicable(MachineInstr *MI) const { 409259698Sdim const TargetInstrDesc &TID = MI->getDesc(); 410259698Sdim if (!TID.isPredicable()) 411259698Sdim return false; 412259698Sdim 413259698Sdim if ((TID.TSFlags & ARMII::DomainMask) == ARMII::DomainNEON) { 414259698Sdim ARMFunctionInfo *AFI = 415259698Sdim MI->getParent()->getParent()->getInfo<ARMFunctionInfo>(); 416259698Sdim return AFI->isThumb2Function(); 417259698Sdim } 418259698Sdim return true; 419259698Sdim} 420259698Sdim 421259698Sdim/// FIXME: Works around a gcc miscompilation with -fstrict-aliasing. 422259698SdimDISABLE_INLINE 423259698Sdimstatic unsigned getNumJTEntries(const std::vector<MachineJumpTableEntry> &JT, 424259698Sdim unsigned JTI); 425259698Sdimstatic unsigned getNumJTEntries(const std::vector<MachineJumpTableEntry> &JT, 426259698Sdim unsigned JTI) { 427259698Sdim assert(JTI < JT.size()); 428259698Sdim return JT[JTI].MBBs.size(); 429259698Sdim} 430259698Sdim 431259698Sdim/// GetInstSize - Return the size of the specified MachineInstr. 432259698Sdim/// 433259698Sdimunsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { 434259698Sdim const MachineBasicBlock &MBB = *MI->getParent(); 435259698Sdim const MachineFunction *MF = MBB.getParent(); 436259698Sdim const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo(); 437259698Sdim 438259698Sdim // Basic size info comes from the TSFlags field. 439259698Sdim const TargetInstrDesc &TID = MI->getDesc(); 440259698Sdim unsigned TSFlags = TID.TSFlags; 441259698Sdim 442259698Sdim unsigned Opc = MI->getOpcode(); 443259698Sdim switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) { 444259698Sdim default: { 445259698Sdim // If this machine instr is an inline asm, measure it. 446259698Sdim if (MI->getOpcode() == ARM::INLINEASM) 447259698Sdim return getInlineAsmLength(MI->getOperand(0).getSymbolName(), *MAI); 448259698Sdim if (MI->isLabel()) 449259698Sdim return 0; 450259698Sdim switch (Opc) { 451259698Sdim default: 452259698Sdim llvm_unreachable("Unknown or unset size field for instr!"); 453259698Sdim case TargetInstrInfo::IMPLICIT_DEF: 454259698Sdim case TargetInstrInfo::KILL: 455259698Sdim case TargetInstrInfo::DBG_LABEL: 456259698Sdim case TargetInstrInfo::EH_LABEL: 457259698Sdim return 0; 458259698Sdim } 459259698Sdim break; 460259698Sdim } 461259698Sdim case ARMII::Size8Bytes: return 8; // ARM instruction x 2. 462259698Sdim case ARMII::Size4Bytes: return 4; // ARM / Thumb2 instruction. 463259698Sdim case ARMII::Size2Bytes: return 2; // Thumb1 instruction. 464259698Sdim case ARMII::SizeSpecial: { 465259698Sdim switch (Opc) { 466276479Sdim case ARM::CONSTPOOL_ENTRY: 467259698Sdim // If this machine instr is a constant pool entry, its size is recorded as 468259698Sdim // operand #2. 469259698Sdim return MI->getOperand(2).getImm(); 470276479Sdim case ARM::Int_eh_sjlj_setjmp: 471259698Sdim return 24; 472259698Sdim case ARM::tInt_eh_sjlj_setjmp: 473259698Sdim return 22; 474259698Sdim case ARM::t2Int_eh_sjlj_setjmp: 475259698Sdim return 22; 476259698Sdim case ARM::BR_JTr: 477259698Sdim case ARM::BR_JTm: 478259698Sdim case ARM::BR_JTadd: 479259698Sdim case ARM::tBR_JTr: 480259698Sdim case ARM::t2BR_JT: 481259698Sdim case ARM::t2TBB: 482259698Sdim case ARM::t2TBH: { 483259698Sdim // These are jumptable branches, i.e. a branch followed by an inlined 484259698Sdim // jumptable. The size is 4 + 4 * number of entries. For TBB, each 485259698Sdim // entry is one byte; TBH two byte each. 486259698Sdim unsigned EntrySize = (Opc == ARM::t2TBB) 487259698Sdim ? 1 : ((Opc == ARM::t2TBH) ? 2 : 4); 488259698Sdim unsigned NumOps = TID.getNumOperands(); 489259698Sdim MachineOperand JTOP = 490259698Sdim MI->getOperand(NumOps - (TID.isPredicable() ? 3 : 2)); 491259698Sdim unsigned JTI = JTOP.getIndex(); 492259698Sdim const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 493259698Sdim const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 494259698Sdim assert(JTI < JT.size()); 495259698Sdim // Thumb instructions are 2 byte aligned, but JT entries are 4 byte 496259698Sdim // 4 aligned. The assembler / linker may add 2 byte padding just before 497288943Sdim // the JT entries. The size does not include this padding; the 498288943Sdim // constant islands pass does separate bookkeeping for it. 499288943Sdim // FIXME: If we know the size of the function is less than (1 << 16) *2 500288943Sdim // bytes, we can use 16-bit entries instead. Then there won't be an 501259698Sdim // alignment issue. 502259698Sdim unsigned InstSize = (Opc == ARM::tBR_JTr || Opc == ARM::t2BR_JT) ? 2 : 4; 503259698Sdim unsigned NumEntries = getNumJTEntries(JT, JTI); 504259698Sdim if (Opc == ARM::t2TBB && (NumEntries & 1)) 505259698Sdim // Make sure the instruction that follows TBB is 2-byte aligned. 506259698Sdim // FIXME: Constant island pass should insert an "ALIGN" instruction 507259698Sdim // instead. 508259698Sdim ++NumEntries; 509259698Sdim return NumEntries * EntrySize + InstSize; 510259698Sdim } 511259698Sdim default: 512259698Sdim // Otherwise, pseudo-instruction sizes are zero. 513259698Sdim return 0; 514259698Sdim } 515259698Sdim } 516259698Sdim } 517259698Sdim return 0; // Not reached 518276479Sdim} 519259698Sdim 520259698Sdim/// Return true if the instruction is a register to register move and 521259698Sdim/// leave the source and dest operands in the passed parameters. 522259698Sdim/// 523259698Sdimbool 524259698SdimARMBaseInstrInfo::isMoveInstr(const MachineInstr &MI, 525259698Sdim unsigned &SrcReg, unsigned &DstReg, 526259698Sdim unsigned& SrcSubIdx, unsigned& DstSubIdx) const { 527259698Sdim SrcSubIdx = DstSubIdx = 0; // No sub-registers. 528259698Sdim 529259698Sdim switch (MI.getOpcode()) { 530259698Sdim default: break; 531259698Sdim case ARM::VMOVS: 532259698Sdim case ARM::VMOVD: 533259698Sdim case ARM::VMOVDneon: 534276479Sdim case ARM::VMOVQ: { 535259698Sdim SrcReg = MI.getOperand(1).getReg(); 536259698Sdim DstReg = MI.getOperand(0).getReg(); 537259698Sdim return true; 538259698Sdim } 539259698Sdim case ARM::MOVr: 540259698Sdim case ARM::tMOVr: 541259698Sdim case ARM::tMOVgpr2tgpr: 542259698Sdim case ARM::tMOVtgpr2gpr: 543259698Sdim case ARM::tMOVgpr2gpr: 544259698Sdim case ARM::t2MOVr: { 545259698Sdim assert(MI.getDesc().getNumOperands() >= 2 && 546259698Sdim MI.getOperand(0).isReg() && 547259698Sdim MI.getOperand(1).isReg() && 548259698Sdim "Invalid ARM MOV instruction"); 549259698Sdim SrcReg = MI.getOperand(1).getReg(); 550259698Sdim DstReg = MI.getOperand(0).getReg(); 551259698Sdim return true; 552259698Sdim } 553259698Sdim } 554259698Sdim 555259698Sdim return false; 556259698Sdim} 557259698Sdim 558259698Sdimunsigned 559259698SdimARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, 560259698Sdim int &FrameIndex) const { 561259698Sdim switch (MI->getOpcode()) { 562259698Sdim default: break; 563259698Sdim case ARM::LDR: 564259698Sdim case ARM::t2LDRs: // FIXME: don't use t2LDRs to access frame. 565259698Sdim if (MI->getOperand(1).isFI() && 566259698Sdim MI->getOperand(2).isReg() && 567259698Sdim MI->getOperand(3).isImm() && 568259698Sdim MI->getOperand(2).getReg() == 0 && 569259698Sdim MI->getOperand(3).getImm() == 0) { 570259698Sdim FrameIndex = MI->getOperand(1).getIndex(); 571259698Sdim return MI->getOperand(0).getReg(); 572259698Sdim } 573259698Sdim break; 574259698Sdim case ARM::t2LDRi12: 575259698Sdim case ARM::tRestore: 576259698Sdim if (MI->getOperand(1).isFI() && 577259698Sdim MI->getOperand(2).isImm() && 578259698Sdim MI->getOperand(2).getImm() == 0) { 579259698Sdim FrameIndex = MI->getOperand(1).getIndex(); 580259698Sdim return MI->getOperand(0).getReg(); 581259698Sdim } 582259698Sdim break; 583259698Sdim case ARM::VLDRD: 584259698Sdim case ARM::VLDRS: 585259698Sdim if (MI->getOperand(1).isFI() && 586259698Sdim MI->getOperand(2).isImm() && 587259698Sdim MI->getOperand(2).getImm() == 0) { 588259698Sdim FrameIndex = MI->getOperand(1).getIndex(); 589259698Sdim return MI->getOperand(0).getReg(); 590259698Sdim } 591259698Sdim break; 592259698Sdim } 593259698Sdim 594259698Sdim return 0; 595259698Sdim} 596259698Sdim 597259698Sdimunsigned 598259698SdimARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI, 599259698Sdim int &FrameIndex) const { 600259698Sdim switch (MI->getOpcode()) { 601259698Sdim default: break; 602259698Sdim case ARM::STR: 603259698Sdim case ARM::t2STRs: // FIXME: don't use t2STRs to access frame. 604259698Sdim if (MI->getOperand(1).isFI() && 605259698Sdim MI->getOperand(2).isReg() && 606259698Sdim MI->getOperand(3).isImm() && 607259698Sdim MI->getOperand(2).getReg() == 0 && 608259698Sdim MI->getOperand(3).getImm() == 0) { 609259698Sdim FrameIndex = MI->getOperand(1).getIndex(); 610259698Sdim return MI->getOperand(0).getReg(); 611259698Sdim } 612259698Sdim break; 613259698Sdim case ARM::t2STRi12: 614259698Sdim case ARM::tSpill: 615259698Sdim if (MI->getOperand(1).isFI() && 616259698Sdim MI->getOperand(2).isImm() && 617259698Sdim MI->getOperand(2).getImm() == 0) { 618259698Sdim FrameIndex = MI->getOperand(1).getIndex(); 619259698Sdim return MI->getOperand(0).getReg(); 620259698Sdim } 621259698Sdim break; 622259698Sdim case ARM::VSTRD: 623259698Sdim case ARM::VSTRS: 624259698Sdim if (MI->getOperand(1).isFI() && 625259698Sdim MI->getOperand(2).isImm() && 626259698Sdim MI->getOperand(2).getImm() == 0) { 627259698Sdim FrameIndex = MI->getOperand(1).getIndex(); 628259698Sdim return MI->getOperand(0).getReg(); 629259698Sdim } 630259698Sdim break; 631259698Sdim } 632259698Sdim 633259698Sdim return 0; 634259698Sdim} 635259698Sdim 636259698Sdimbool 637259698SdimARMBaseInstrInfo::copyRegToReg(MachineBasicBlock &MBB, 638259698Sdim MachineBasicBlock::iterator I, 639259698Sdim unsigned DestReg, unsigned SrcReg, 640259698Sdim const TargetRegisterClass *DestRC, 641259698Sdim const TargetRegisterClass *SrcRC) const { 642259698Sdim DebugLoc DL = DebugLoc::getUnknownLoc(); 643259698Sdim if (I != MBB.end()) DL = I->getDebugLoc(); 644259698Sdim 645259698Sdim if (DestRC != SrcRC) { 646259698Sdim if (DestRC->getSize() != SrcRC->getSize()) 647259698Sdim return false; 648259698Sdim 649259698Sdim // Allow DPR / DPR_VFP2 / DPR_8 cross-class copies. 650259698Sdim // Allow QPR / QPR_VFP2 / QPR_8 cross-class copies. 651259698Sdim if (DestRC->getSize() != 8 && DestRC->getSize() != 16) 652259698Sdim return false; 653276479Sdim } 654259698Sdim 655259698Sdim if (DestRC == ARM::GPRRegisterClass) { 656259698Sdim AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::MOVr), 657259698Sdim DestReg).addReg(SrcReg))); 658259698Sdim } else if (DestRC == ARM::SPRRegisterClass) { 659259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVS), DestReg) 660259698Sdim .addReg(SrcReg)); 661259698Sdim } else if (DestRC == ARM::DPRRegisterClass) { 662259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVD), DestReg) 663259698Sdim .addReg(SrcReg)); 664259698Sdim } else if (DestRC == ARM::DPR_VFP2RegisterClass || 665259698Sdim DestRC == ARM::DPR_8RegisterClass || 666259698Sdim SrcRC == ARM::DPR_VFP2RegisterClass || 667259698Sdim SrcRC == ARM::DPR_8RegisterClass) { 668259698Sdim // Always use neon reg-reg move if source or dest is NEON-only regclass. 669259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVDneon), 670259698Sdim DestReg).addReg(SrcReg)); 671259698Sdim } else if (DestRC == ARM::QPRRegisterClass || 672259698Sdim DestRC == ARM::QPR_VFP2RegisterClass || 673259698Sdim DestRC == ARM::QPR_8RegisterClass) { 674259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVQ), 675259698Sdim DestReg).addReg(SrcReg)); 676259698Sdim } else { 677259698Sdim return false; 678259698Sdim } 679259698Sdim 680259698Sdim return true; 681259698Sdim} 682259698Sdim 683259698Sdimvoid ARMBaseInstrInfo:: 684259698SdimstoreRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, 685259698Sdim unsigned SrcReg, bool isKill, int FI, 686259698Sdim const TargetRegisterClass *RC) const { 687259698Sdim DebugLoc DL = DebugLoc::getUnknownLoc(); 688259698Sdim if (I != MBB.end()) DL = I->getDebugLoc(); 689259698Sdim MachineFunction &MF = *MBB.getParent(); 690259698Sdim MachineFrameInfo &MFI = *MF.getFrameInfo(); 691259698Sdim unsigned Align = MFI.getObjectAlignment(FI); 692259698Sdim 693259698Sdim MachineMemOperand *MMO = 694259698Sdim MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI), 695259698Sdim MachineMemOperand::MOStore, 0, 696259698Sdim MFI.getObjectSize(FI), 697259698Sdim Align); 698259698Sdim 699259698Sdim if (RC == ARM::GPRRegisterClass) { 700259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STR)) 701259698Sdim .addReg(SrcReg, getKillRegState(isKill)) 702259698Sdim .addFrameIndex(FI).addReg(0).addImm(0).addMemOperand(MMO)); 703259698Sdim } else if (RC == ARM::DPRRegisterClass || 704259698Sdim RC == ARM::DPR_VFP2RegisterClass || 705259698Sdim RC == ARM::DPR_8RegisterClass) { 706259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRD)) 707259698Sdim .addReg(SrcReg, getKillRegState(isKill)) 708259698Sdim .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); 709259698Sdim } else if (RC == ARM::SPRRegisterClass) { 710259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRS)) 711259698Sdim .addReg(SrcReg, getKillRegState(isKill)) 712259698Sdim .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); 713259698Sdim } else { 714259698Sdim assert((RC == ARM::QPRRegisterClass || 715259698Sdim RC == ARM::QPR_VFP2RegisterClass) && "Unknown regclass!"); 716259698Sdim // FIXME: Neon instructions should support predicates 717259698Sdim if (Align >= 16 718259698Sdim && (getRegisterInfo().needsStackRealignment(MF))) { 719259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1q64)) 720259698Sdim .addFrameIndex(FI).addImm(0).addImm(0).addImm(128) 721259698Sdim .addMemOperand(MMO) 722259698Sdim .addReg(SrcReg, getKillRegState(isKill))); 723259698Sdim } else { 724259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRQ)). 725259698Sdim addReg(SrcReg, getKillRegState(isKill)) 726259698Sdim .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); 727259698Sdim } 728259698Sdim } 729259698Sdim} 730259698Sdim 731259698Sdimvoid ARMBaseInstrInfo:: 732259698SdimloadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, 733259698Sdim unsigned DestReg, int FI, 734259698Sdim const TargetRegisterClass *RC) const { 735259698Sdim DebugLoc DL = DebugLoc::getUnknownLoc(); 736259698Sdim if (I != MBB.end()) DL = I->getDebugLoc(); 737259698Sdim MachineFunction &MF = *MBB.getParent(); 738259698Sdim MachineFrameInfo &MFI = *MF.getFrameInfo(); 739259698Sdim unsigned Align = MFI.getObjectAlignment(FI); 740276479Sdim 741276479Sdim MachineMemOperand *MMO = 742259698Sdim MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI), 743259698Sdim MachineMemOperand::MOLoad, 0, 744259698Sdim MFI.getObjectSize(FI), 745259698Sdim Align); 746259698Sdim 747259698Sdim if (RC == ARM::GPRRegisterClass) { 748259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDR), DestReg) 749259698Sdim .addFrameIndex(FI).addReg(0).addImm(0).addMemOperand(MMO)); 750259698Sdim } else if (RC == ARM::DPRRegisterClass || 751259698Sdim RC == ARM::DPR_VFP2RegisterClass || 752259698Sdim RC == ARM::DPR_8RegisterClass) { 753259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRD), DestReg) 754259698Sdim .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); 755259698Sdim } else if (RC == ARM::SPRRegisterClass) { 756259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRS), DestReg) 757259698Sdim .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); 758259698Sdim } else { 759259698Sdim assert((RC == ARM::QPRRegisterClass || 760259698Sdim RC == ARM::QPR_VFP2RegisterClass || 761259698Sdim RC == ARM::QPR_8RegisterClass) && "Unknown regclass!"); 762276479Sdim if (Align >= 16 763259698Sdim && (getRegisterInfo().needsStackRealignment(MF))) { 764259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1q64), DestReg) 765259698Sdim .addFrameIndex(FI).addImm(0).addImm(0).addImm(128) 766259698Sdim .addMemOperand(MMO)); 767259698Sdim } else { 768259698Sdim AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRQ), DestReg) 769259698Sdim .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); 770259698Sdim } 771259698Sdim } 772259698Sdim} 773259698Sdim 774259698SdimMachineInstr *ARMBaseInstrInfo:: 775259698SdimfoldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI, 776259698Sdim const SmallVectorImpl<unsigned> &Ops, int FI) const { 777259698Sdim if (Ops.size() != 1) return NULL; 778259698Sdim 779259698Sdim unsigned OpNum = Ops[0]; 780259698Sdim unsigned Opc = MI->getOpcode(); 781259698Sdim MachineInstr *NewMI = NULL; 782259698Sdim if (Opc == ARM::MOVr || Opc == ARM::t2MOVr) { 783259698Sdim // If it is updating CPSR, then it cannot be folded. 784259698Sdim if (MI->getOperand(4).getReg() == ARM::CPSR && !MI->getOperand(4).isDead()) 785259698Sdim return NULL; 786259698Sdim unsigned Pred = MI->getOperand(2).getImm(); 787259698Sdim unsigned PredReg = MI->getOperand(3).getReg(); 788259698Sdim if (OpNum == 0) { // move -> store 789259698Sdim unsigned SrcReg = MI->getOperand(1).getReg(); 790259698Sdim unsigned SrcSubReg = MI->getOperand(1).getSubReg(); 791259698Sdim bool isKill = MI->getOperand(1).isKill(); 792259698Sdim bool isUndef = MI->getOperand(1).isUndef(); 793259698Sdim if (Opc == ARM::MOVr) 794259698Sdim NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::STR)) 795259698Sdim .addReg(SrcReg, 796259698Sdim getKillRegState(isKill) | getUndefRegState(isUndef), 797259698Sdim SrcSubReg) 798259698Sdim .addFrameIndex(FI).addReg(0).addImm(0).addImm(Pred).addReg(PredReg); 799259698Sdim else // ARM::t2MOVr 800259698Sdim NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2STRi12)) 801259698Sdim .addReg(SrcReg, 802259698Sdim getKillRegState(isKill) | getUndefRegState(isUndef), 803259698Sdim SrcSubReg) 804259698Sdim .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg); 805259698Sdim } else { // move -> load 806259698Sdim unsigned DstReg = MI->getOperand(0).getReg(); 807259698Sdim unsigned DstSubReg = MI->getOperand(0).getSubReg(); 808259698Sdim bool isDead = MI->getOperand(0).isDead(); 809259698Sdim bool isUndef = MI->getOperand(0).isUndef(); 810259698Sdim if (Opc == ARM::MOVr) 811259698Sdim NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::LDR)) 812259698Sdim .addReg(DstReg, 813259698Sdim RegState::Define | 814259698Sdim getDeadRegState(isDead) | 815259698Sdim getUndefRegState(isUndef), DstSubReg) 816259698Sdim .addFrameIndex(FI).addReg(0).addImm(0).addImm(Pred).addReg(PredReg); 817259698Sdim else // ARM::t2MOVr 818259698Sdim NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2LDRi12)) 819259698Sdim .addReg(DstReg, 820259698Sdim RegState::Define | 821259698Sdim getDeadRegState(isDead) | 822259698Sdim getUndefRegState(isUndef), DstSubReg) 823259698Sdim .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg); 824259698Sdim } 825259698Sdim } else if (Opc == ARM::tMOVgpr2gpr || 826259698Sdim Opc == ARM::tMOVtgpr2gpr || 827259698Sdim Opc == ARM::tMOVgpr2tgpr) { 828259698Sdim if (OpNum == 0) { // move -> store 829259698Sdim unsigned SrcReg = MI->getOperand(1).getReg(); 830259698Sdim unsigned SrcSubReg = MI->getOperand(1).getSubReg(); 831259698Sdim bool isKill = MI->getOperand(1).isKill(); 832259698Sdim bool isUndef = MI->getOperand(1).isUndef(); 833259698Sdim NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2STRi12)) 834259698Sdim .addReg(SrcReg, 835259698Sdim getKillRegState(isKill) | getUndefRegState(isUndef), 836259698Sdim SrcSubReg) 837259698Sdim .addFrameIndex(FI).addImm(0).addImm(ARMCC::AL).addReg(0); 838259698Sdim } else { // move -> load 839259698Sdim unsigned DstReg = MI->getOperand(0).getReg(); 840259698Sdim unsigned DstSubReg = MI->getOperand(0).getSubReg(); 841259698Sdim bool isDead = MI->getOperand(0).isDead(); 842259698Sdim bool isUndef = MI->getOperand(0).isUndef(); 843259698Sdim NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2LDRi12)) 844259698Sdim .addReg(DstReg, 845259698Sdim RegState::Define | 846259698Sdim getDeadRegState(isDead) | 847259698Sdim getUndefRegState(isUndef), 848259698Sdim DstSubReg) 849259698Sdim .addFrameIndex(FI).addImm(0).addImm(ARMCC::AL).addReg(0); 850259698Sdim } 851259698Sdim } else if (Opc == ARM::VMOVS) { 852259698Sdim unsigned Pred = MI->getOperand(2).getImm(); 853259698Sdim unsigned PredReg = MI->getOperand(3).getReg(); 854259698Sdim if (OpNum == 0) { // move -> store 855259698Sdim unsigned SrcReg = MI->getOperand(1).getReg(); 856259698Sdim unsigned SrcSubReg = MI->getOperand(1).getSubReg(); 857259698Sdim bool isKill = MI->getOperand(1).isKill(); 858259698Sdim bool isUndef = MI->getOperand(1).isUndef(); 859259698Sdim NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::VSTRS)) 860259698Sdim .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef), 861259698Sdim SrcSubReg) 862259698Sdim .addFrameIndex(FI) 863259698Sdim .addImm(0).addImm(Pred).addReg(PredReg); 864259698Sdim } else { // move -> load 865259698Sdim unsigned DstReg = MI->getOperand(0).getReg(); 866259698Sdim unsigned DstSubReg = MI->getOperand(0).getSubReg(); 867259698Sdim bool isDead = MI->getOperand(0).isDead(); 868259698Sdim bool isUndef = MI->getOperand(0).isUndef(); 869276479Sdim NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::VLDRS)) 870259698Sdim .addReg(DstReg, 871259698Sdim RegState::Define | 872259698Sdim getDeadRegState(isDead) | 873276479Sdim getUndefRegState(isUndef), 874259698Sdim DstSubReg) 875259698Sdim .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg); 876259698Sdim } 877259698Sdim } 878259698Sdim else if (Opc == ARM::VMOVD) { 879259698Sdim unsigned Pred = MI->getOperand(2).getImm(); 880259698Sdim unsigned PredReg = MI->getOperand(3).getReg(); 881259698Sdim if (OpNum == 0) { // move -> store 882259698Sdim unsigned SrcReg = MI->getOperand(1).getReg(); 883259698Sdim unsigned SrcSubReg = MI->getOperand(1).getSubReg(); 884259698Sdim bool isKill = MI->getOperand(1).isKill(); 885259698Sdim bool isUndef = MI->getOperand(1).isUndef(); 886288943Sdim NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::VSTRD)) 887259698Sdim .addReg(SrcReg, 888259698Sdim getKillRegState(isKill) | getUndefRegState(isUndef), 889259698Sdim SrcSubReg) 890259698Sdim .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg); 891276479Sdim } else { // move -> load 892276479Sdim unsigned DstReg = MI->getOperand(0).getReg(); 893276479Sdim unsigned DstSubReg = MI->getOperand(0).getSubReg(); 894259698Sdim bool isDead = MI->getOperand(0).isDead(); 895259698Sdim bool isUndef = MI->getOperand(0).isUndef(); 896259698Sdim NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::VLDRD)) 897259698Sdim .addReg(DstReg, 898276479Sdim RegState::Define | 899259698Sdim getDeadRegState(isDead) | 900259698Sdim getUndefRegState(isUndef), 901259698Sdim DstSubReg) 902296417Sdim .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg); 903259698Sdim } 904259698Sdim } 905259698Sdim 906259698Sdim return NewMI; 907259698Sdim} 908259698Sdim 909296417SdimMachineInstr* 910259698SdimARMBaseInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, 911259698Sdim MachineInstr* MI, 912276479Sdim const SmallVectorImpl<unsigned> &Ops, 913259698Sdim MachineInstr* LoadMI) const { 914259698Sdim // FIXME 915259698Sdim return 0; 916259698Sdim} 917259698Sdim 918259698Sdimbool 919259698SdimARMBaseInstrInfo::canFoldMemoryOperand(const MachineInstr *MI, 920259698Sdim const SmallVectorImpl<unsigned> &Ops) const { 921259698Sdim if (Ops.size() != 1) return false; 922259698Sdim 923259698Sdim unsigned Opc = MI->getOpcode(); 924259698Sdim if (Opc == ARM::MOVr || Opc == ARM::t2MOVr) { 925276479Sdim // If it is updating CPSR, then it cannot be folded. 926288943Sdim return MI->getOperand(4).getReg() != ARM::CPSR || 927259698Sdim MI->getOperand(4).isDead(); 928259698Sdim } else if (Opc == ARM::tMOVgpr2gpr || 929259698Sdim Opc == ARM::tMOVtgpr2gpr || 930259698Sdim Opc == ARM::tMOVgpr2tgpr) { 931259698Sdim return true; 932259698Sdim } else if (Opc == ARM::VMOVS || Opc == ARM::VMOVD) { 933259698Sdim return true; 934259698Sdim } else if (Opc == ARM::VMOVDneon || Opc == ARM::VMOVQ) { 935259698Sdim return false; // FIXME 936259698Sdim } 937259698Sdim 938259698Sdim return false; 939259698Sdim} 940259698Sdim 941259698Sdim/// Create a copy of a const pool value. Update CPI to the new index and return 942259698Sdim/// the label UID. 943259698Sdimstatic unsigned duplicateCPV(MachineFunction &MF, unsigned &CPI) { 944259698Sdim MachineConstantPool *MCP = MF.getConstantPool(); 945259698Sdim ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 946259698Sdim 947259698Sdim const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI]; 948259698Sdim assert(MCPE.isMachineConstantPoolEntry() && 949259698Sdim "Expecting a machine constantpool entry!"); 950259698Sdim ARMConstantPoolValue *ACPV = 951259698Sdim static_cast<ARMConstantPoolValue*>(MCPE.Val.MachineCPVal); 952259698Sdim 953259698Sdim unsigned PCLabelId = AFI->createConstPoolEntryUId(); 954 ARMConstantPoolValue *NewCPV = 0; 955 if (ACPV->isGlobalValue()) 956 NewCPV = new ARMConstantPoolValue(ACPV->getGV(), PCLabelId, 957 ARMCP::CPValue, 4); 958 else if (ACPV->isExtSymbol()) 959 NewCPV = new ARMConstantPoolValue(MF.getFunction()->getContext(), 960 ACPV->getSymbol(), PCLabelId, 4); 961 else if (ACPV->isBlockAddress()) 962 NewCPV = new ARMConstantPoolValue(ACPV->getBlockAddress(), PCLabelId, 963 ARMCP::CPBlockAddress, 4); 964 else 965 llvm_unreachable("Unexpected ARM constantpool value type!!"); 966 CPI = MCP->getConstantPoolIndex(NewCPV, MCPE.getAlignment()); 967 return PCLabelId; 968} 969 970void ARMBaseInstrInfo:: 971reMaterialize(MachineBasicBlock &MBB, 972 MachineBasicBlock::iterator I, 973 unsigned DestReg, unsigned SubIdx, 974 const MachineInstr *Orig, 975 const TargetRegisterInfo *TRI) const { 976 if (SubIdx && TargetRegisterInfo::isPhysicalRegister(DestReg)) { 977 DestReg = TRI->getSubReg(DestReg, SubIdx); 978 SubIdx = 0; 979 } 980 981 unsigned Opcode = Orig->getOpcode(); 982 switch (Opcode) { 983 default: { 984 MachineInstr *MI = MBB.getParent()->CloneMachineInstr(Orig); 985 MI->getOperand(0).setReg(DestReg); 986 MBB.insert(I, MI); 987 break; 988 } 989 case ARM::tLDRpci_pic: 990 case ARM::t2LDRpci_pic: { 991 MachineFunction &MF = *MBB.getParent(); 992 unsigned CPI = Orig->getOperand(1).getIndex(); 993 unsigned PCLabelId = duplicateCPV(MF, CPI); 994 MachineInstrBuilder MIB = BuildMI(MBB, I, Orig->getDebugLoc(), get(Opcode), 995 DestReg) 996 .addConstantPoolIndex(CPI).addImm(PCLabelId); 997 (*MIB).setMemRefs(Orig->memoperands_begin(), Orig->memoperands_end()); 998 break; 999 } 1000 } 1001 1002 MachineInstr *NewMI = prior(I); 1003 NewMI->getOperand(0).setSubReg(SubIdx); 1004} 1005 1006MachineInstr * 1007ARMBaseInstrInfo::duplicate(MachineInstr *Orig, MachineFunction &MF) const { 1008 MachineInstr *MI = TargetInstrInfoImpl::duplicate(Orig, MF); 1009 switch(Orig->getOpcode()) { 1010 case ARM::tLDRpci_pic: 1011 case ARM::t2LDRpci_pic: { 1012 unsigned CPI = Orig->getOperand(1).getIndex(); 1013 unsigned PCLabelId = duplicateCPV(MF, CPI); 1014 Orig->getOperand(1).setIndex(CPI); 1015 Orig->getOperand(2).setImm(PCLabelId); 1016 break; 1017 } 1018 } 1019 return MI; 1020} 1021 1022bool ARMBaseInstrInfo::isIdentical(const MachineInstr *MI0, 1023 const MachineInstr *MI1, 1024 const MachineRegisterInfo *MRI) const { 1025 int Opcode = MI0->getOpcode(); 1026 if (Opcode == ARM::t2LDRpci || 1027 Opcode == ARM::t2LDRpci_pic || 1028 Opcode == ARM::tLDRpci || 1029 Opcode == ARM::tLDRpci_pic) { 1030 if (MI1->getOpcode() != Opcode) 1031 return false; 1032 if (MI0->getNumOperands() != MI1->getNumOperands()) 1033 return false; 1034 1035 const MachineOperand &MO0 = MI0->getOperand(1); 1036 const MachineOperand &MO1 = MI1->getOperand(1); 1037 if (MO0.getOffset() != MO1.getOffset()) 1038 return false; 1039 1040 const MachineFunction *MF = MI0->getParent()->getParent(); 1041 const MachineConstantPool *MCP = MF->getConstantPool(); 1042 int CPI0 = MO0.getIndex(); 1043 int CPI1 = MO1.getIndex(); 1044 const MachineConstantPoolEntry &MCPE0 = MCP->getConstants()[CPI0]; 1045 const MachineConstantPoolEntry &MCPE1 = MCP->getConstants()[CPI1]; 1046 ARMConstantPoolValue *ACPV0 = 1047 static_cast<ARMConstantPoolValue*>(MCPE0.Val.MachineCPVal); 1048 ARMConstantPoolValue *ACPV1 = 1049 static_cast<ARMConstantPoolValue*>(MCPE1.Val.MachineCPVal); 1050 return ACPV0->hasSameValue(ACPV1); 1051 } 1052 1053 return TargetInstrInfoImpl::isIdentical(MI0, MI1, MRI); 1054} 1055 1056/// getInstrPredicate - If instruction is predicated, returns its predicate 1057/// condition, otherwise returns AL. It also returns the condition code 1058/// register by reference. 1059ARMCC::CondCodes 1060llvm::getInstrPredicate(const MachineInstr *MI, unsigned &PredReg) { 1061 int PIdx = MI->findFirstPredOperandIdx(); 1062 if (PIdx == -1) { 1063 PredReg = 0; 1064 return ARMCC::AL; 1065 } 1066 1067 PredReg = MI->getOperand(PIdx+1).getReg(); 1068 return (ARMCC::CondCodes)MI->getOperand(PIdx).getImm(); 1069} 1070 1071 1072int llvm::getMatchingCondBranchOpcode(int Opc) { 1073 if (Opc == ARM::B) 1074 return ARM::Bcc; 1075 else if (Opc == ARM::tB) 1076 return ARM::tBcc; 1077 else if (Opc == ARM::t2B) 1078 return ARM::t2Bcc; 1079 1080 llvm_unreachable("Unknown unconditional branch opcode!"); 1081 return 0; 1082} 1083 1084 1085void llvm::emitARMRegPlusImmediate(MachineBasicBlock &MBB, 1086 MachineBasicBlock::iterator &MBBI, DebugLoc dl, 1087 unsigned DestReg, unsigned BaseReg, int NumBytes, 1088 ARMCC::CondCodes Pred, unsigned PredReg, 1089 const ARMBaseInstrInfo &TII) { 1090 bool isSub = NumBytes < 0; 1091 if (isSub) NumBytes = -NumBytes; 1092 1093 while (NumBytes) { 1094 unsigned RotAmt = ARM_AM::getSOImmValRotate(NumBytes); 1095 unsigned ThisVal = NumBytes & ARM_AM::rotr32(0xFF, RotAmt); 1096 assert(ThisVal && "Didn't extract field correctly"); 1097 1098 // We will handle these bits from offset, clear them. 1099 NumBytes &= ~ThisVal; 1100 1101 assert(ARM_AM::getSOImmVal(ThisVal) != -1 && "Bit extraction didn't work?"); 1102 1103 // Build the new ADD / SUB. 1104 unsigned Opc = isSub ? ARM::SUBri : ARM::ADDri; 1105 BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) 1106 .addReg(BaseReg, RegState::Kill).addImm(ThisVal) 1107 .addImm((unsigned)Pred).addReg(PredReg).addReg(0); 1108 BaseReg = DestReg; 1109 } 1110} 1111 1112bool llvm::rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, 1113 unsigned FrameReg, int &Offset, 1114 const ARMBaseInstrInfo &TII) { 1115 unsigned Opcode = MI.getOpcode(); 1116 const TargetInstrDesc &Desc = MI.getDesc(); 1117 unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); 1118 bool isSub = false; 1119 1120 // Memory operands in inline assembly always use AddrMode2. 1121 if (Opcode == ARM::INLINEASM) 1122 AddrMode = ARMII::AddrMode2; 1123 1124 if (Opcode == ARM::ADDri) { 1125 Offset += MI.getOperand(FrameRegIdx+1).getImm(); 1126 if (Offset == 0) { 1127 // Turn it into a move. 1128 MI.setDesc(TII.get(ARM::MOVr)); 1129 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 1130 MI.RemoveOperand(FrameRegIdx+1); 1131 Offset = 0; 1132 return true; 1133 } else if (Offset < 0) { 1134 Offset = -Offset; 1135 isSub = true; 1136 MI.setDesc(TII.get(ARM::SUBri)); 1137 } 1138 1139 // Common case: small offset, fits into instruction. 1140 if (ARM_AM::getSOImmVal(Offset) != -1) { 1141 // Replace the FrameIndex with sp / fp 1142 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 1143 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); 1144 Offset = 0; 1145 return true; 1146 } 1147 1148 // Otherwise, pull as much of the immedidate into this ADDri/SUBri 1149 // as possible. 1150 unsigned RotAmt = ARM_AM::getSOImmValRotate(Offset); 1151 unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xFF, RotAmt); 1152 1153 // We will handle these bits from offset, clear them. 1154 Offset &= ~ThisImmVal; 1155 1156 // Get the properly encoded SOImmVal field. 1157 assert(ARM_AM::getSOImmVal(ThisImmVal) != -1 && 1158 "Bit extraction didn't work?"); 1159 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal); 1160 } else { 1161 unsigned ImmIdx = 0; 1162 int InstrOffs = 0; 1163 unsigned NumBits = 0; 1164 unsigned Scale = 1; 1165 switch (AddrMode) { 1166 case ARMII::AddrMode2: { 1167 ImmIdx = FrameRegIdx+2; 1168 InstrOffs = ARM_AM::getAM2Offset(MI.getOperand(ImmIdx).getImm()); 1169 if (ARM_AM::getAM2Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub) 1170 InstrOffs *= -1; 1171 NumBits = 12; 1172 break; 1173 } 1174 case ARMII::AddrMode3: { 1175 ImmIdx = FrameRegIdx+2; 1176 InstrOffs = ARM_AM::getAM3Offset(MI.getOperand(ImmIdx).getImm()); 1177 if (ARM_AM::getAM3Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub) 1178 InstrOffs *= -1; 1179 NumBits = 8; 1180 break; 1181 } 1182 case ARMII::AddrMode4: 1183 case ARMII::AddrMode6: 1184 // Can't fold any offset even if it's zero. 1185 return false; 1186 case ARMII::AddrMode5: { 1187 ImmIdx = FrameRegIdx+1; 1188 InstrOffs = ARM_AM::getAM5Offset(MI.getOperand(ImmIdx).getImm()); 1189 if (ARM_AM::getAM5Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub) 1190 InstrOffs *= -1; 1191 NumBits = 8; 1192 Scale = 4; 1193 break; 1194 } 1195 default: 1196 llvm_unreachable("Unsupported addressing mode!"); 1197 break; 1198 } 1199 1200 Offset += InstrOffs * Scale; 1201 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); 1202 if (Offset < 0) { 1203 Offset = -Offset; 1204 isSub = true; 1205 } 1206 1207 // Attempt to fold address comp. if opcode has offset bits 1208 if (NumBits > 0) { 1209 // Common case: small offset, fits into instruction. 1210 MachineOperand &ImmOp = MI.getOperand(ImmIdx); 1211 int ImmedOffset = Offset / Scale; 1212 unsigned Mask = (1 << NumBits) - 1; 1213 if ((unsigned)Offset <= Mask * Scale) { 1214 // Replace the FrameIndex with sp 1215 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 1216 if (isSub) 1217 ImmedOffset |= 1 << NumBits; 1218 ImmOp.ChangeToImmediate(ImmedOffset); 1219 Offset = 0; 1220 return true; 1221 } 1222 1223 // Otherwise, it didn't fit. Pull in what we can to simplify the immed. 1224 ImmedOffset = ImmedOffset & Mask; 1225 if (isSub) 1226 ImmedOffset |= 1 << NumBits; 1227 ImmOp.ChangeToImmediate(ImmedOffset); 1228 Offset &= ~(Mask*Scale); 1229 } 1230 } 1231 1232 Offset = (isSub) ? -Offset : Offset; 1233 return Offset == 0; 1234} 1235