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