Thumb1RegisterInfo.cpp revision 5a96b3dad2f634c9081c8b2b6c2575441dc5a2bd
131c24bf5b39cc8391d4cfdbf8cf5163975fdb81eJim Grosbach//===- Thumb1RegisterInfo.cpp - Thumb-1 Register Information ----*- C++ -*-===//
2a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//
3a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//                     The LLVM Compiler Infrastructure
4a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//
5a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// This file is distributed under the University of Illinois Open Source
6a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// License. See LICENSE.TXT for details.
7a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//
8a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//===----------------------------------------------------------------------===//
9a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//
1031c24bf5b39cc8391d4cfdbf8cf5163975fdb81eJim Grosbach// This file contains the Thumb-1 implementation of the TargetRegisterInfo
1131c24bf5b39cc8391d4cfdbf8cf5163975fdb81eJim Grosbach// class.
12a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//
13a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//===----------------------------------------------------------------------===//
14a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
15a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARM.h"
1677521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin#include "ARMBaseInstrInfo.h"
17a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMMachineFunctionInfo.h"
18a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMSubtarget.h"
19b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin#include "Thumb1InstrInfo.h"
20b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin#include "Thumb1RegisterInfo.h"
21ee04a6d3a40c3017124e3fd89a0db473a2824498Evan Cheng#include "MCTargetDesc/ARMAddressingModes.h"
22a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/Constants.h"
23a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/DerivedTypes.h"
249adc0abad3c3ed40a268ccbcee0c74cb9e1359feOwen Anderson#include "llvm/Function.h"
259adc0abad3c3ed40a268ccbcee0c74cb9e1359feOwen Anderson#include "llvm/LLVMContext.h"
26a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineConstantPool.h"
27a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineFrameInfo.h"
28a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineFunction.h"
29a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineInstrBuilder.h"
30a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineRegisterInfo.h"
3116c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov#include "llvm/Target/TargetFrameLowering.h"
32a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/Target/TargetMachine.h"
334e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach#include "llvm/Support/CommandLine.h"
34ab7c09b6b6f4516a631fd6788918c237c83939afTorok Edwin#include "llvm/Support/ErrorHandling.h"
35dac237e18209b697a8ba122d0ddd9cad4dfba1f8Torok Edwin#include "llvm/Support/raw_ostream.h"
36a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
378c407d45964fbba19719be555324f247e4fb14e1Dan Gohmannamespace llvm {
384e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbachextern cl::opt<bool> ReuseFrameIndexVals;
398c407d45964fbba19719be555324f247e4fb14e1Dan Gohman}
408c407d45964fbba19719be555324f247e4fb14e1Dan Gohman
418c407d45964fbba19719be555324f247e4fb14e1Dan Gohmanusing namespace llvm;
424e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach
43db5a71a8e01ed9a0d93a19176df6ea0aea510d7bDavid GoodwinThumb1RegisterInfo::Thumb1RegisterInfo(const ARMBaseInstrInfo &tii,
44b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin                                       const ARMSubtarget &sti)
45a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  : ARMBaseRegisterInfo(tii, sti) {
46a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
47a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
48c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesenconst TargetRegisterClass*
49c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund OlesenThumb1RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC)
50c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen                                                                         const {
51fa226bccaa90c520cac154df74069bbabb976eabJakob Stoklund Olesen  if (ARM::tGPRRegClass.hasSubClassEq(RC))
52c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen    return ARM::tGPRRegisterClass;
53c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen  return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC);
54c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen}
55c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen
561db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesenconst TargetRegisterClass *
571db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund OlesenThumb1RegisterInfo::getPointerRegClass(unsigned Kind) const {
581db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesen  return ARM::tGPRRegisterClass;
591db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesen}
601db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesen
61a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitLoadConstPool - Emits a load from constpool to materialize the
62a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// specified immediate.
633daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikovvoid
643daccd82d3151fa3629de430b55698a81084fc9eAnton KorobeynikovThumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB,
653daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                      MachineBasicBlock::iterator &MBBI,
663daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                      DebugLoc dl,
673daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                      unsigned DestReg, unsigned SubIdx,
683daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                      int Val,
693daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                      ARMCC::CondCodes Pred, unsigned PredReg,
703daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                      unsigned MIFlags) const {
71a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  MachineFunction &MF = *MBB.getParent();
72a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  MachineConstantPool *ConstantPool = MF.getConstantPool();
7346510a73e977273ec67747eb34cbdb43f815e451Dan Gohman  const Constant *C = ConstantInt::get(
741d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson          Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val);
75a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
76a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
773e333637f172c30adf5c8333b592fbde17ff9f78Jim Grosbach  BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRpci))
78b3fcc06d2124f9d01e3b48097b44cc141309908eAnton Korobeynikov    .addReg(DestReg, getDefRegState(true), SubIdx)
79b3fcc06d2124f9d01e3b48097b44cc141309908eAnton Korobeynikov    .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg)
80b3fcc06d2124f9d01e3b48097b44cc141309908eAnton Korobeynikov    .setMIFlags(MIFlags);
81a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
82a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
83446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
84a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize
85a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// a destreg = basereg + immediate in Thumb code. Materialize the immediate
86a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// in a register using mov / mvn sequences or load the immediate from a
87a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constpool entry.
88a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic
89a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovvoid emitThumbRegPlusImmInReg(MachineBasicBlock &MBB,
90a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              MachineBasicBlock::iterator &MBBI,
913daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                              DebugLoc dl,
92a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              unsigned DestReg, unsigned BaseReg,
93a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              int NumBytes, bool CanChangeCC,
94a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              const TargetInstrInfo &TII,
95e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach                              const ARMBaseRegisterInfo& MRI,
963daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                              unsigned MIFlags = MachineInstr::NoFlags) {
973d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach    MachineFunction &MF = *MBB.getParent();
9855ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov    bool isHigh = !isARMLowRegister(DestReg) ||
9955ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov                  (BaseReg != 0 && !isARMLowRegister(BaseReg));
100a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    bool isSub = false;
101a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Subtract doesn't have high register version. Load the negative value
102a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // if either base or dest register is a high register. Also, if do not
103a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // issue sub as part of the sequence if condition register is to be
104a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // preserved.
105a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (NumBytes < 0 && !isHigh && CanChangeCC) {
106a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      isSub = true;
107a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      NumBytes = -NumBytes;
108a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
109a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned LdReg = DestReg;
110a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (DestReg == ARM::SP) {
111a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      assert(BaseReg == ARM::SP && "Unexpected!");
11265c58daa8b8985d2116216043103009815a55e77Jim Grosbach      LdReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass);
113a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
114a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
115a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (NumBytes <= 255 && NumBytes >= 0)
116b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng      AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg))
1173daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov        .addImm(NumBytes).setMIFlags(MIFlags);
118a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    else if (NumBytes < 0 && NumBytes >= -255) {
119b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng      AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg))
1203daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov        .addImm(NumBytes).setMIFlags(MIFlags);
121b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng      AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg))
1223daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov        .addReg(LdReg, RegState::Kill).setMIFlags(MIFlags);
123a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    } else
1243daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov      MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes,
1253daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                            ARMCC::AL, 0, MIFlags);
126a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
127a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Emit add / sub.
128a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr);
129446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    MachineInstrBuilder MIB =
130446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
131446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    if (Opc != ARM::tADDhirr)
132b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng      MIB = AddDefaultT1CC(MIB);
133a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (DestReg == ARM::SP || isSub)
134a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill);
135a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    else
136a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill);
137446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    AddDefaultPred(MIB);
138a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
139a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
140a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// calcNumMI - Returns the number of instructions required to materialize
141a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// the specific add / sub r, c instruction.
142a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic unsigned calcNumMI(int Opc, int ExtraOpc, unsigned Bytes,
143a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                          unsigned NumBits, unsigned Scale) {
144a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned NumMIs = 0;
145a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Chunk = ((1 << NumBits) - 1) * Scale;
146a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
147a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (Opc == ARM::tADDrSPi) {
148a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
149a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Bytes -= ThisVal;
150a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumMIs++;
151a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumBits = 8;
152a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Scale = 1;  // Followed by a number of tADDi8.
153a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Chunk = ((1 << NumBits) - 1) * Scale;
154a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
155a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
156a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  NumMIs += Bytes / Chunk;
157a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if ((Bytes % Chunk) != 0)
158a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumMIs++;
159a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (ExtraOpc)
160a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumMIs++;
161a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  return NumMIs;
162a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
163a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
164a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize
165a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// a destreg = basereg + immediate in Thumb code.
166e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbachvoid llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
167e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach                                     MachineBasicBlock::iterator &MBBI,
16857caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                     DebugLoc dl,
169e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach                                     unsigned DestReg, unsigned BaseReg,
170e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach                                     int NumBytes, const TargetInstrInfo &TII,
1713daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                     const ARMBaseRegisterInfo& MRI,
1723daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                     unsigned MIFlags) {
173a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  bool isSub = NumBytes < 0;
174a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Bytes = (unsigned)NumBytes;
175a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (isSub) Bytes = -NumBytes;
176a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  bool isMul4 = (Bytes & 3) == 0;
177a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  bool isTwoAddr = false;
178a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  bool DstNotEqBase = false;
179a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned NumBits = 1;
180a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Scale = 1;
181a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  int Opc = 0;
182a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  int ExtraOpc = 0;
183446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  bool NeedCC = false;
184a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
185a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (DestReg == BaseReg && BaseReg == ARM::SP) {
186a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!");
187a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumBits = 7;
188a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Scale = 4;
189a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
190a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    isTwoAddr = true;
191a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  } else if (!isSub && BaseReg == ARM::SP) {
192a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r1 = add sp, 403
193a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // =>
194a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r1 = add sp, 100 * 4
195a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r1 = add r1, 3
196a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (!isMul4) {
197a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Bytes &= ~3;
198a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ExtraOpc = ARM::tADDi3;
199a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
200a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumBits = 8;
201a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Scale = 4;
202a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Opc = ARM::tADDrSPi;
203a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  } else {
204a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // sp = sub sp, c
205a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r1 = sub sp, c
206a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r8 = sub sp, c
207a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (DestReg != BaseReg)
208a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      DstNotEqBase = true;
209a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumBits = 8;
210f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng    if (DestReg == ARM::SP) {
211f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
212f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!");
213f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      NumBits = 7;
214f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      Scale = 4;
215f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng    } else {
216f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
217f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      NumBits = 8;
2185b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach      NeedCC = true;
219f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng    }
220a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    isTwoAddr = true;
221a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
222a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
223a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale);
224a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2;
225a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (NumMIs > Threshold) {
226a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // This will expand into too many instructions. Load the immediate from a
227a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // constpool entry.
2283daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov    emitThumbRegPlusImmInReg(MBB, MBBI, dl,
2293daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                             DestReg, BaseReg, NumBytes, true,
2303daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                             TII, MRI, MIFlags);
231a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    return;
232a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
233a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
234a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (DstNotEqBase) {
23555ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov    if (isARMLowRegister(DestReg) && isARMLowRegister(BaseReg)) {
236a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // If both are low registers, emit DestReg = add BaseReg, max(Imm, 7)
237a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      unsigned Chunk = (1 << 3) - 1;
238a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
239a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Bytes -= ThisVal;
240e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng      const MCInstrDesc &MCID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3);
241446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      const MachineInstrBuilder MIB =
2424372ca6fe4119d708d43d9c9ac3feafc7607952aJim Grosbach        AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)
2434372ca6fe4119d708d43d9c9ac3feafc7607952aJim Grosbach                         .setMIFlags(MIFlags));
244446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal));
245a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    } else {
24663b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach      AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
24763b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach        .addReg(BaseReg, RegState::Kill))
2483daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov        .setMIFlags(MIFlags);
249a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
250a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    BaseReg = DestReg;
251a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
252a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
253a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Chunk = ((1 << NumBits) - 1) * Scale;
254a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  while (Bytes) {
255a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
256a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Bytes -= ThisVal;
257a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    ThisVal /= Scale;
258a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Build the new tADD / tSUB.
259446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    if (isTwoAddr) {
260446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
261446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      if (NeedCC)
262b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng        MIB = AddDefaultT1CC(MIB);
2633daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov      MIB.addReg(DestReg).addImm(ThisVal);
2645b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach      MIB = AddDefaultPred(MIB);
2653daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov      MIB.setMIFlags(MIFlags);
2668884148b8e8f19d5484e735618cf188cfa02c626Jim Grosbach    } else {
267a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      bool isKill = BaseReg != ARM::SP;
268446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
269446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      if (NeedCC)
270b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng        MIB = AddDefaultT1CC(MIB);
271446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal);
2725b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach      MIB = AddDefaultPred(MIB);
2733daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov      MIB.setMIFlags(MIFlags);
274a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
2753daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov      BaseReg = DestReg;
276a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      if (Opc == ARM::tADDrSPi) {
277a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        // r4 = add sp, imm
278a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        // r4 = add r4, imm
279a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        // ...
280a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        NumBits = 8;
281a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        Scale = 1;
282a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        Chunk = ((1 << NumBits) - 1) * Scale;
283a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
2845b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach        NeedCC = isTwoAddr = true;
285a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      }
286a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
287a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
288a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
289446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  if (ExtraOpc) {
290e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng    const MCInstrDesc &MCID = TII.get(ExtraOpc);
291e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng    AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg))
292446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng                   .addReg(DestReg, RegState::Kill)
2933daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                   .addImm(((unsigned)NumBytes) & 3)
2943daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                   .setMIFlags(MIFlags));
295446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  }
296a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
297a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
29855ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikovstatic void emitSPUpdate(MachineBasicBlock &MBB,
29955ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov                         MachineBasicBlock::iterator &MBBI,
30055ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov                         const TargetInstrInfo &TII, DebugLoc dl,
301b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin                         const Thumb1RegisterInfo &MRI,
30255ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov                         int NumBytes) {
30357caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov  emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, TII,
30457caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                            MRI);
305a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
306a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
307b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo::
308a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton KorobeynikoveliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
309a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              MachineBasicBlock::iterator I) const {
31016c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
311d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov
312d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov  if (!TFI->hasReservedCallFrame(MF)) {
313a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // If we have alloca, convert as follows:
314a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // ADJCALLSTACKDOWN -> sub, sp, sp, amount
315a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // ADJCALLSTACKUP   -> add, sp, sp, amount
316a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    MachineInstr *Old = I;
317a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    DebugLoc dl = Old->getDebugLoc();
318a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Amount = Old->getOperand(0).getImm();
319a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (Amount != 0) {
320a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // We need to keep the stack aligned properly.  To do this, we round the
321a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // amount of space needed for the outgoing arguments up to the next
322a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // alignment boundary.
32316c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov      unsigned Align = TFI->getStackAlignment();
324a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Amount = (Amount+Align-1)/Align*Align;
325a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
326a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Replace the pseudo instruction with a new instruction...
327a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      unsigned Opc = Old->getOpcode();
328a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
32955ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov        emitSPUpdate(MBB, I, TII, dl, *this, -Amount);
330a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      } else {
331a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
33255ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov        emitSPUpdate(MBB, I, TII, dl, *this, Amount);
333a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      }
334a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
335a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
336a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  MBB.erase(I);
337a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
338a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
339a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbConstant - Emit a series of instructions to materialize a
340a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constant.
341a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic void emitThumbConstant(MachineBasicBlock &MBB,
342a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              MachineBasicBlock::iterator &MBBI,
343a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              unsigned DestReg, int Imm,
344a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              const TargetInstrInfo &TII,
345b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin                              const Thumb1RegisterInfo& MRI,
346a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              DebugLoc dl) {
347a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  bool isSub = Imm < 0;
348a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (isSub) Imm = -Imm;
349a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
350a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  int Chunk = (1 << 8) - 1;
351a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  int ThisVal = (Imm > Chunk) ? Chunk : Imm;
352a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  Imm -= ThisVal;
353b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng  AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8),
354b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng                                        DestReg))
355446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng                 .addImm(ThisVal));
356a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (Imm > 0)
35757caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov    emitThumbRegPlusImmediate(MBB, MBBI, dl, DestReg, DestReg, Imm, TII, MRI);
358446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  if (isSub) {
359e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng    const MCInstrDesc &MCID = TII.get(ARM::tRSB);
360e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng    AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg))
361446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng                   .addReg(DestReg, RegState::Kill));
362446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  }
363446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng}
364446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
365446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Chengstatic void removeOperands(MachineInstr &MI, unsigned i) {
366446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  unsigned Op = i;
367446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  for (unsigned e = MI.getNumOperands(); i != e; ++i)
368446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    MI.RemoveOperand(Op);
369a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
370a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
3717a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling/// convertToNonSPOpcode - Change the opcode to the non-SP version, because
3727a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling/// we're replacing the frame index with a non-SP register.
3737a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendlingstatic unsigned convertToNonSPOpcode(unsigned Opcode) {
3747a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  switch (Opcode) {
3757a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  case ARM::tLDRspi:
3767a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    return ARM::tLDRi;
3777a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
3787a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  case ARM::tSTRspi:
3797a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    return ARM::tSTRi;
3807a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  }
3817a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
3827a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  return Opcode;
3837a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling}
3847a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
38574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool Thumb1RegisterInfo::
38674d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachrewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
38774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                  unsigned FrameReg, int &Offset,
38874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                  const ARMBaseInstrInfo &TII) const {
389a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  MachineInstr &MI = *II;
390a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  MachineBasicBlock &MBB = *MI.getParent();
391a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  DebugLoc dl = MI.getDebugLoc();
392a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Opcode = MI.getOpcode();
393e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  const MCInstrDesc &Desc = MI.getDesc();
394a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
395a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
396a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (Opcode == ARM::tADDrSPi) {
39774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    Offset += MI.getOperand(FrameRegIdx+1).getImm();
398a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
399a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Can't use tADDrSPi if it's based off the frame pointer.
400a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned NumBits = 0;
401a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Scale = 1;
402a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (FrameReg != ARM::SP) {
403a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Opcode = ARM::tADDi3;
404a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      NumBits = 3;
405a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    } else {
406a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      NumBits = 8;
407a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Scale = 4;
408a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      assert((Offset & 3) == 0 &&
409a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov             "Thumb add/sub sp, #imm immediate must be multiple of 4!");
410a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
411a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
41235f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen    unsigned PredReg;
41335f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen    if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) {
414a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Turn it into a move.
4152a7b41ba4d3eb3c6003f6768dc20b28d83eac265Jim Grosbach      MI.setDesc(TII.get(ARM::tMOVr));
41674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
4175b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach      // Remove offset
41863b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach      MI.RemoveOperand(FrameRegIdx+1);
41963b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach      MachineInstrBuilder MIB(&MI);
42074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      return true;
421a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
422a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
423a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Common case: small offset, fits into instruction.
424a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Mask = (1 << NumBits) - 1;
425a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (((Offset / Scale) & ~Mask) == 0) {
426a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Replace the FrameIndex with sp / fp
427446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      if (Opcode == ARM::tADDi3) {
4285b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach        MI.setDesc(TII.get(Opcode));
42974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        removeOperands(MI, FrameRegIdx);
430446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng        MachineInstrBuilder MIB(&MI);
431b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng        AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg)
432f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng                       .addImm(Offset / Scale));
433446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      } else {
43474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
43574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset / Scale);
436446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      }
43774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      return true;
438a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
439a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
440a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned DestReg = MI.getOperand(0).getReg();
441a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Bytes = (Offset > 0) ? Offset : -Offset;
442a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned NumMIs = calcNumMI(Opcode, 0, Bytes, NumBits, Scale);
443a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // MI would expand into a large number of instructions. Don't try to
444a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // simplify the immediate.
445a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (NumMIs > 2) {
44657caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov      emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII,
44757caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                *this);
448a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      MBB.erase(II);
44974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      return true;
450a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
451a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
452a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (Offset > 0) {
453a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Translate r0 = add sp, imm to
454a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // r0 = add sp, 255*4
455a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // r0 = add r0, (imm - 255*4)
456446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      if (Opcode == ARM::tADDi3) {
45729b9d7e4ea7521be25bccdb66ecd9c9df5ed8b4bChad Rosier        MI.setDesc(TII.get(Opcode));
45874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        removeOperands(MI, FrameRegIdx);
459446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng        MachineInstrBuilder MIB(&MI);
460b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng        AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg).addImm(Mask));
461446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      } else {
46274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
46374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Mask);
464446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      }
465a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Offset = (Offset - Mask * Scale);
4667896c9f436a4eda5ec15e882a7505ba482a2fcd0Chris Lattner      MachineBasicBlock::iterator NII = llvm::next(II);
46757caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov      emitThumbRegPlusImmediate(MBB, NII, dl, DestReg, DestReg, Offset, TII,
46857caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                *this);
469a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    } else {
470a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Translate r0 = add sp, -imm to
471a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // r0 = -imm (this is then translated into a series of instructons)
472a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // r0 = add r0, sp
473a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      emitThumbConstant(MBB, II, DestReg, Offset, TII, *this, dl);
474bae20a6353583089224b94280a2dd69805dca247Evan Cheng
475a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      MI.setDesc(TII.get(ARM::tADDhirr));
47674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false, false, true);
47774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      MI.getOperand(FrameRegIdx+1).ChangeToRegister(FrameReg, false);
478a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
47974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    return true;
480a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  } else {
4817a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    if (AddrMode != ARMII::AddrModeT1_s)
482c23197a26f34f559ea9797de51e187087c039c42Torok Edwin      llvm_unreachable("Unsupported addressing mode!");
4837a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
4847a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    unsigned ImmIdx = FrameRegIdx + 1;
4857a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    int InstrOffs = MI.getOperand(ImmIdx).getImm();
4867a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5;
4877a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    unsigned Scale = 4;
488a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
489a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Offset += InstrOffs * Scale;
4907a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!");
491a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
492a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Common case: small offset, fits into instruction.
493a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    MachineOperand &ImmOp = MI.getOperand(ImmIdx);
494a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    int ImmedOffset = Offset / Scale;
495a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Mask = (1 << NumBits) - 1;
4967a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
497a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if ((unsigned)Offset <= Mask * Scale) {
4987a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      // Replace the FrameIndex with the frame register (e.g., sp).
49974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
500a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ImmOp.ChangeToImmediate(ImmedOffset);
5017a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
5027a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      // If we're using a register where sp was stored, convert the instruction
5037a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      // to the non-SP version.
5047a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      unsigned NewOpc = convertToNonSPOpcode(Opcode);
5057a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      if (NewOpc != Opcode && FrameReg != ARM::SP)
5067a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling        MI.setDesc(TII.get(NewOpc));
5077a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
50874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      return true;
509a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
510a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
5117a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    NumBits = 5;
5127a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    Mask = (1 << NumBits) - 1;
5137a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
514a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // If this is a thumb spill / restore, we will be using a constpool load to
515a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // materialize the offset.
51674472b4bf963c424da04f42dffdb94c85ef964bcJim Grosbach    if (Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {
517a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ImmOp.ChangeToImmediate(0);
5187a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    } else {
519a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
520a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ImmedOffset = ImmedOffset & Mask;
521a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ImmOp.ChangeToImmediate(ImmedOffset);
5227a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      Offset &= ~(Mask * Scale);
523a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
524a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
5257a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
52674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  return Offset == 0;
52774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach}
52874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
52974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachvoid
53074d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I,
53174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                      unsigned BaseReg, int64_t Offset) const {
53274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  MachineInstr &MI = *I;
53374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  int Off = Offset; // ARM doesn't need the general 64-bit offsets
53474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned i = 0;
53574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
53674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  while (!MI.getOperand(i).isFI()) {
53774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    ++i;
53874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
53974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
5401f6a329f79b3568d379142f921f59c4143ddaa14Duncan Sands  bool Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII);
54174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  assert (Done && "Unable to resolve frame index!");
5421f6a329f79b3568d379142f921f59c4143ddaa14Duncan Sands  (void)Done;
54374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach}
54474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
54574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// saveScavengerRegister - Spill the register so it can be used by the
54674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// register scavenger. Return true.
54774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool
54874d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB,
54974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                          MachineBasicBlock::iterator I,
55074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                          MachineBasicBlock::iterator &UseMI,
55174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                          const TargetRegisterClass *RC,
55274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                          unsigned Reg) const {
55374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // Thumb1 can't use the emergency spill slot on the stack because
55474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // ldr/str immediate offsets must be positive, and if we're referencing
55574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // off the frame pointer (if, for example, there are alloca() calls in
55674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // the function, the offset will be negative. Use R12 instead since that's
55774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // a call clobbered register that we know won't be used in Thumb1 mode.
55874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  DebugLoc DL;
5592a7b41ba4d3eb3c6003f6768dc20b28d83eac265Jim Grosbach  AddDefaultPred(BuildMI(MBB, I, DL, TII.get(ARM::tMOVr))
56063b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach    .addReg(ARM::R12, RegState::Define)
56163b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach    .addReg(Reg, RegState::Kill));
56274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
56374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // The UseMI is where we would like to restore the register. If there's
56474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // interference with R12 before then, however, we'll need to restore it
56574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // before that instead and adjust the UseMI.
56674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  bool done = false;
56774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) {
56874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    if (II->isDebugValue())
56974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      continue;
57074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    // If this instruction affects R12, adjust our restore point.
57174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) {
57274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      const MachineOperand &MO = II->getOperand(i);
57374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      if (!MO.isReg() || MO.isUndef() || !MO.getReg() ||
57474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach          TargetRegisterInfo::isVirtualRegister(MO.getReg()))
57574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        continue;
57674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      if (MO.getReg() == ARM::R12) {
57774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        UseMI = II;
57874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        done = true;
57974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        break;
58074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      }
58174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    }
58274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
58374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // Restore the register from R12
5842a7b41ba4d3eb3c6003f6768dc20b28d83eac265Jim Grosbach  AddDefaultPred(BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVr)).
58563b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach    addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill));
58674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
58774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  return true;
58874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach}
58974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
590fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbachvoid
59174d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
592fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach                                        int SPAdj, RegScavenger *RS) const {
59374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned VReg = 0;
59474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned i = 0;
59574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  MachineInstr &MI = *II;
59674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  MachineBasicBlock &MBB = *MI.getParent();
59774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  MachineFunction &MF = *MBB.getParent();
59874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
59974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  DebugLoc dl = MI.getDebugLoc();
60074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
60174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  while (!MI.getOperand(i).isFI()) {
60274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    ++i;
60374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
60474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
60574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
60674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned FrameReg = ARM::SP;
60774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  int FrameIndex = MI.getOperand(i).getIndex();
60874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
60974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach               MF.getFrameInfo()->getStackSize() + SPAdj;
61074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
611ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach  if (AFI->isGPRCalleeSavedArea1Frame(FrameIndex))
612ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach    Offset -= AFI->getGPRCalleeSavedArea1Offset();
613ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach  else if (AFI->isGPRCalleeSavedArea2Frame(FrameIndex))
614ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach    Offset -= AFI->getGPRCalleeSavedArea2Offset();
61574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  else if (MF.getFrameInfo()->hasVarSizedObjects()) {
61616c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov    assert(SPAdj == 0 && MF.getTarget().getFrameLowering()->hasFP(MF) &&
6177920d96964d707a3af85332c98d95b2fabc3d5c9Benjamin Kramer           "Unexpected");
61874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    // There are alloca()'s in this function, must reference off the frame
61965482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach    // pointer or base pointer instead.
62065482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach    if (!hasBasePointer(MF)) {
62165482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach      FrameReg = getFrameRegister(MF);
62265482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach      Offset -= AFI->getFramePtrSpillOffset();
62365482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach    } else
62465482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach      FrameReg = BasePtr;
62574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
62674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
62774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // Special handling of dbg_value instructions.
62874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  if (MI.isDebugValue()) {
62974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    MI.getOperand(i).  ChangeToRegister(FrameReg, false /*isDef*/);
63074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    MI.getOperand(i+1).ChangeToImmediate(Offset);
631fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach    return;
63274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
63374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
63474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // Modify MI as necessary to handle as much of 'Offset' as possible
63574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  assert(AFI->isThumbFunction() &&
63674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach         "This eliminateFrameIndex only supports Thumb1!");
63774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  if (rewriteFrameIndex(MI, i, FrameReg, Offset, TII))
638fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach    return;
639a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
640a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  // If we get here, the immediate doesn't fit into the instruction.  We folded
641a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  // as much as possible above, handle the rest, providing a register that is
642a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  // SP+LargeImm.
643a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  assert(Offset && "This code isn't needed if offset already handled!");
644a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
64574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned Opcode = MI.getOpcode();
64674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
647446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  // Remove predicate first.
648446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  int PIdx = MI.findFirstPredOperandIdx();
649446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  if (PIdx != -1)
650446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    removeOperands(MI, PIdx);
651446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
6525a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng  if (MI.mayLoad()) {
653a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Use the destination register to materialize sp + offset.
654a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned TmpReg = MI.getOperand(0).getReg();
655a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    bool UseRR = false;
65674472b4bf963c424da04f42dffdb94c85ef964bcJim Grosbach    if (Opcode == ARM::tLDRspi) {
657a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      if (FrameReg == ARM::SP)
6583daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov        emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg,
6593daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                 Offset, false, TII, *this);
660a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      else {
661378445303b10b092a898a75131141a8259cff50bEvan Cheng        emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset);
662a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        UseRR = true;
663a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      }
664446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    } else {
66557caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov      emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII,
66657caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                *this);
667446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    }
668446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
6696e90ce21cc2b0627ee9219e3fb0cf808f2b73328Eric Christopher    MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi));
670a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    MI.getOperand(i).ChangeToRegister(TmpReg, false, false, true);
671a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (UseRR)
6725f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach      // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
6735f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach      // register. The offset is already handled in the vreg value.
6745f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach      MI.getOperand(i+1).ChangeToRegister(FrameReg, false, false, false);
6755a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng  } else if (MI.mayStore()) {
676b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach      VReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass);
6773d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach      bool UseRR = false;
678b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach
67974472b4bf963c424da04f42dffdb94c85ef964bcJim Grosbach      if (Opcode == ARM::tSTRspi) {
6803d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach        if (FrameReg == ARM::SP)
6813daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov          emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg,
6823daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                   Offset, false, TII, *this);
6833d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach        else {
684b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach          emitLoadConstPool(MBB, II, dl, VReg, 0, Offset);
6853d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach          UseRR = true;
6863d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach        }
6873d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach      } else
68857caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov        emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII,
68957caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                  *this);
6906e90ce21cc2b0627ee9219e3fb0cf808f2b73328Eric Christopher      MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi));
691b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach      MI.getOperand(i).ChangeToRegister(VReg, false, false, true);
6925f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach      if (UseRR)
6935f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach        // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
6945f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach        // register. The offset is already handled in the vreg value.
6955f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach        MI.getOperand(i+1).ChangeToRegister(FrameReg, false, false, false);
696f4caf69720d807573c50d41aa06bcec1c99bdbbdBill Wendling  } else {
697a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    assert(false && "Unexpected opcode!");
698f4caf69720d807573c50d41aa06bcec1c99bdbbdBill Wendling  }
699446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
700446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  // Add predicate back if it's needed.
7015a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng  if (MI.isPredicable()) {
702446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    MachineInstrBuilder MIB(&MI);
703446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    AddDefaultPred(MIB);
704446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  }
705a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
706