Thumb1RegisterInfo.cpp revision fa226bccaa90c520cac154df74069bbabb976eab
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"
16a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMAddressingModes.h"
1777521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin#include "ARMBaseInstrInfo.h"
18a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMMachineFunctionInfo.h"
19a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMSubtarget.h"
20b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin#include "Thumb1InstrInfo.h"
21b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin#include "Thumb1RegisterInfo.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/MachineLocation.h"
31a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineRegisterInfo.h"
3216c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov#include "llvm/Target/TargetFrameLowering.h"
33a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/Target/TargetMachine.h"
344e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach#include "llvm/Support/CommandLine.h"
35ab7c09b6b6f4516a631fd6788918c237c83939afTorok Edwin#include "llvm/Support/ErrorHandling.h"
36dac237e18209b697a8ba122d0ddd9cad4dfba1f8Torok Edwin#include "llvm/Support/raw_ostream.h"
37a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
388c407d45964fbba19719be555324f247e4fb14e1Dan Gohmannamespace llvm {
394e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbachextern cl::opt<bool> ReuseFrameIndexVals;
408c407d45964fbba19719be555324f247e4fb14e1Dan Gohman}
418c407d45964fbba19719be555324f247e4fb14e1Dan Gohman
428c407d45964fbba19719be555324f247e4fb14e1Dan Gohmanusing namespace llvm;
434e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach
44db5a71a8e01ed9a0d93a19176df6ea0aea510d7bDavid GoodwinThumb1RegisterInfo::Thumb1RegisterInfo(const ARMBaseInstrInfo &tii,
45b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin                                       const ARMSubtarget &sti)
46a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  : ARMBaseRegisterInfo(tii, sti) {
47a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
48a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
49c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesenconst TargetRegisterClass*
50c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund OlesenThumb1RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC)
51c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen                                                                         const {
52fa226bccaa90c520cac154df74069bbabb976eabJakob Stoklund Olesen  if (ARM::tGPRRegClass.hasSubClassEq(RC))
53c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen    return ARM::tGPRRegisterClass;
54c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen  return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC);
55c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen}
56c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen
571db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesenconst TargetRegisterClass *
581db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund OlesenThumb1RegisterInfo::getPointerRegClass(unsigned Kind) const {
591db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesen  return ARM::tGPRRegisterClass;
601db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesen}
611db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesen
62a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitLoadConstPool - Emits a load from constpool to materialize the
63a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// specified immediate.
643daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikovvoid
653daccd82d3151fa3629de430b55698a81084fc9eAnton KorobeynikovThumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB,
663daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                      MachineBasicBlock::iterator &MBBI,
673daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                      DebugLoc dl,
683daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                      unsigned DestReg, unsigned SubIdx,
693daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                      int Val,
703daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                      ARMCC::CondCodes Pred, unsigned PredReg,
713daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                      unsigned MIFlags) const {
72a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  MachineFunction &MF = *MBB.getParent();
73a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  MachineConstantPool *ConstantPool = MF.getConstantPool();
7446510a73e977273ec67747eb34cbdb43f815e451Dan Gohman  const Constant *C = ConstantInt::get(
751d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson          Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val);
76a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
77a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
783e333637f172c30adf5c8333b592fbde17ff9f78Jim Grosbach  BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRpci))
79b3fcc06d2124f9d01e3b48097b44cc141309908eAnton Korobeynikov    .addReg(DestReg, getDefRegState(true), SubIdx)
80b3fcc06d2124f9d01e3b48097b44cc141309908eAnton Korobeynikov    .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg)
81b3fcc06d2124f9d01e3b48097b44cc141309908eAnton Korobeynikov    .setMIFlags(MIFlags);
82a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
83a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
84446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
85a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize
86a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// a destreg = basereg + immediate in Thumb code. Materialize the immediate
87a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// in a register using mov / mvn sequences or load the immediate from a
88a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constpool entry.
89a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic
90a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovvoid emitThumbRegPlusImmInReg(MachineBasicBlock &MBB,
91a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              MachineBasicBlock::iterator &MBBI,
923daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                              DebugLoc dl,
93a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              unsigned DestReg, unsigned BaseReg,
94a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              int NumBytes, bool CanChangeCC,
95a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              const TargetInstrInfo &TII,
96e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach                              const ARMBaseRegisterInfo& MRI,
973daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                              unsigned MIFlags = MachineInstr::NoFlags) {
983d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach    MachineFunction &MF = *MBB.getParent();
9955ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov    bool isHigh = !isARMLowRegister(DestReg) ||
10055ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov                  (BaseReg != 0 && !isARMLowRegister(BaseReg));
101a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    bool isSub = false;
102a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Subtract doesn't have high register version. Load the negative value
103a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // if either base or dest register is a high register. Also, if do not
104a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // issue sub as part of the sequence if condition register is to be
105a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // preserved.
106a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (NumBytes < 0 && !isHigh && CanChangeCC) {
107a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      isSub = true;
108a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      NumBytes = -NumBytes;
109a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
110a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned LdReg = DestReg;
111a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (DestReg == ARM::SP) {
112a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      assert(BaseReg == ARM::SP && "Unexpected!");
11365c58daa8b8985d2116216043103009815a55e77Jim Grosbach      LdReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass);
114a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
115a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
116a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (NumBytes <= 255 && NumBytes >= 0)
117b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng      AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg))
1183daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov        .addImm(NumBytes).setMIFlags(MIFlags);
119a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    else if (NumBytes < 0 && NumBytes >= -255) {
120b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng      AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg))
1213daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov        .addImm(NumBytes).setMIFlags(MIFlags);
122b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng      AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg))
1233daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov        .addReg(LdReg, RegState::Kill).setMIFlags(MIFlags);
124a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    } else
1253daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov      MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes,
1263daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                            ARMCC::AL, 0, MIFlags);
127a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
128a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Emit add / sub.
129a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr);
130446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    MachineInstrBuilder MIB =
131446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
132446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    if (Opc != ARM::tADDhirr)
133b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng      MIB = AddDefaultT1CC(MIB);
134a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (DestReg == ARM::SP || isSub)
135a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill);
136a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    else
137a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill);
138446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    AddDefaultPred(MIB);
139a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
140a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
141a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// calcNumMI - Returns the number of instructions required to materialize
142a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// the specific add / sub r, c instruction.
143a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic unsigned calcNumMI(int Opc, int ExtraOpc, unsigned Bytes,
144a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                          unsigned NumBits, unsigned Scale) {
145a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned NumMIs = 0;
146a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Chunk = ((1 << NumBits) - 1) * Scale;
147a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
148a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (Opc == ARM::tADDrSPi) {
149a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
150a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Bytes -= ThisVal;
151a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumMIs++;
152a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumBits = 8;
153a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Scale = 1;  // Followed by a number of tADDi8.
154a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Chunk = ((1 << NumBits) - 1) * Scale;
155a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
156a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
157a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  NumMIs += Bytes / Chunk;
158a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if ((Bytes % Chunk) != 0)
159a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumMIs++;
160a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (ExtraOpc)
161a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumMIs++;
162a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  return NumMIs;
163a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
164a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
165a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize
166a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// a destreg = basereg + immediate in Thumb code.
167e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbachvoid llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
168e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach                                     MachineBasicBlock::iterator &MBBI,
16957caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                     DebugLoc dl,
170e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach                                     unsigned DestReg, unsigned BaseReg,
171e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach                                     int NumBytes, const TargetInstrInfo &TII,
1723daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                     const ARMBaseRegisterInfo& MRI,
1733daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                     unsigned MIFlags) {
174a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  bool isSub = NumBytes < 0;
175a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Bytes = (unsigned)NumBytes;
176a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (isSub) Bytes = -NumBytes;
177a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  bool isMul4 = (Bytes & 3) == 0;
178a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  bool isTwoAddr = false;
179a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  bool DstNotEqBase = false;
180a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned NumBits = 1;
181a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Scale = 1;
182a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  int Opc = 0;
183a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  int ExtraOpc = 0;
184446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  bool NeedCC = false;
185446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  bool NeedPred = false;
186a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
187a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (DestReg == BaseReg && BaseReg == ARM::SP) {
188a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!");
189a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumBits = 7;
190a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Scale = 4;
191a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
192a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    isTwoAddr = true;
193a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  } else if (!isSub && BaseReg == ARM::SP) {
194a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r1 = add sp, 403
195a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // =>
196a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r1 = add sp, 100 * 4
197a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r1 = add r1, 3
198a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (!isMul4) {
199a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Bytes &= ~3;
200a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ExtraOpc = ARM::tADDi3;
201a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
202a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumBits = 8;
203a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Scale = 4;
204a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Opc = ARM::tADDrSPi;
205a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  } else {
206a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // sp = sub sp, c
207a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r1 = sub sp, c
208a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r8 = sub sp, c
209a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (DestReg != BaseReg)
210a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      DstNotEqBase = true;
211a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumBits = 8;
212f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng    if (DestReg == ARM::SP) {
213f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
214f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!");
215f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      NumBits = 7;
216f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      Scale = 4;
217f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng    } else {
218f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
219f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      NumBits = 8;
220f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      NeedPred = NeedCC = true;
221f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng    }
222a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    isTwoAddr = true;
223a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
224a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
225a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale);
226a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2;
227a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (NumMIs > Threshold) {
228a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // This will expand into too many instructions. Load the immediate from a
229a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // constpool entry.
2303daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov    emitThumbRegPlusImmInReg(MBB, MBBI, dl,
2313daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                             DestReg, BaseReg, NumBytes, true,
2323daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                             TII, MRI, MIFlags);
233a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    return;
234a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
235a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
236a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (DstNotEqBase) {
23755ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov    if (isARMLowRegister(DestReg) && isARMLowRegister(BaseReg)) {
238a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // If both are low registers, emit DestReg = add BaseReg, max(Imm, 7)
239a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      unsigned Chunk = (1 << 3) - 1;
240a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
241a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Bytes -= ThisVal;
242446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      const TargetInstrDesc &TID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3);
243446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      const MachineInstrBuilder MIB =
2443daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov        AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg).setMIFlags(MIFlags));
245446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal));
246a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    } else {
247a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
2483daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov        .addReg(BaseReg, RegState::Kill)
2493daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov        .setMIFlags(MIFlags);
250a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
251a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    BaseReg = DestReg;
252a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
253a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
254a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Chunk = ((1 << NumBits) - 1) * Scale;
255a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  while (Bytes) {
256a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
257a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Bytes -= ThisVal;
258a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    ThisVal /= Scale;
259a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Build the new tADD / tSUB.
260446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    if (isTwoAddr) {
261446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
262446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      if (NeedCC)
263b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng        MIB = AddDefaultT1CC(MIB);
2643daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov      MIB.addReg(DestReg).addImm(ThisVal);
265446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      if (NeedPred)
266446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng        MIB = AddDefaultPred(MIB);
2673daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov      MIB.setMIFlags(MIFlags);
268446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    }
269a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    else {
270a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      bool isKill = BaseReg != ARM::SP;
271446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
272446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      if (NeedCC)
273b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng        MIB = AddDefaultT1CC(MIB);
274446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal);
275446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      if (NeedPred)
276446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng        MIB = AddDefaultPred(MIB);
2773daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov      MIB.setMIFlags(MIFlags);
278a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
2793daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov      BaseReg = DestReg;
280a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      if (Opc == ARM::tADDrSPi) {
281a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        // r4 = add sp, imm
282a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        // r4 = add r4, imm
283a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        // ...
284a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        NumBits = 8;
285a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        Scale = 1;
286a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        Chunk = ((1 << NumBits) - 1) * Scale;
287a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
288446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng        NeedPred = NeedCC = isTwoAddr = true;
289a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      }
290a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
291a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
292a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
293446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  if (ExtraOpc) {
294446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    const TargetInstrDesc &TID = TII.get(ExtraOpc);
295b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng    AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg))
296446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng                   .addReg(DestReg, RegState::Kill)
2973daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                   .addImm(((unsigned)NumBytes) & 3)
2983daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                   .setMIFlags(MIFlags));
299446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  }
300a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
301a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
30255ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikovstatic void emitSPUpdate(MachineBasicBlock &MBB,
30355ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov                         MachineBasicBlock::iterator &MBBI,
30455ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov                         const TargetInstrInfo &TII, DebugLoc dl,
305b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin                         const Thumb1RegisterInfo &MRI,
30655ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov                         int NumBytes) {
30757caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov  emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, TII,
30857caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                            MRI);
309a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
310a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
311b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo::
312a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton KorobeynikoveliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
313a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              MachineBasicBlock::iterator I) const {
31416c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
315d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov
316d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov  if (!TFI->hasReservedCallFrame(MF)) {
317a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // If we have alloca, convert as follows:
318a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // ADJCALLSTACKDOWN -> sub, sp, sp, amount
319a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // ADJCALLSTACKUP   -> add, sp, sp, amount
320a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    MachineInstr *Old = I;
321a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    DebugLoc dl = Old->getDebugLoc();
322a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Amount = Old->getOperand(0).getImm();
323a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (Amount != 0) {
324a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // We need to keep the stack aligned properly.  To do this, we round the
325a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // amount of space needed for the outgoing arguments up to the next
326a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // alignment boundary.
32716c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov      unsigned Align = TFI->getStackAlignment();
328a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Amount = (Amount+Align-1)/Align*Align;
329a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
330a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Replace the pseudo instruction with a new instruction...
331a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      unsigned Opc = Old->getOpcode();
332a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
33355ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov        emitSPUpdate(MBB, I, TII, dl, *this, -Amount);
334a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      } else {
335a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
33655ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov        emitSPUpdate(MBB, I, TII, dl, *this, Amount);
337a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      }
338a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
339a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
340a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  MBB.erase(I);
341a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
342a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
343a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbConstant - Emit a series of instructions to materialize a
344a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constant.
345a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic void emitThumbConstant(MachineBasicBlock &MBB,
346a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              MachineBasicBlock::iterator &MBBI,
347a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              unsigned DestReg, int Imm,
348a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              const TargetInstrInfo &TII,
349b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin                              const Thumb1RegisterInfo& MRI,
350a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              DebugLoc dl) {
351a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  bool isSub = Imm < 0;
352a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (isSub) Imm = -Imm;
353a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
354a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  int Chunk = (1 << 8) - 1;
355a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  int ThisVal = (Imm > Chunk) ? Chunk : Imm;
356a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  Imm -= ThisVal;
357b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng  AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8),
358b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng                                        DestReg))
359446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng                 .addImm(ThisVal));
360a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (Imm > 0)
36157caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov    emitThumbRegPlusImmediate(MBB, MBBI, dl, DestReg, DestReg, Imm, TII, MRI);
362446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  if (isSub) {
363446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    const TargetInstrDesc &TID = TII.get(ARM::tRSB);
364b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng    AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg))
365446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng                   .addReg(DestReg, RegState::Kill));
366446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  }
367446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng}
368446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
369446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Chengstatic void removeOperands(MachineInstr &MI, unsigned i) {
370446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  unsigned Op = i;
371446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  for (unsigned e = MI.getNumOperands(); i != e; ++i)
372446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    MI.RemoveOperand(Op);
373a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
374a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
3757a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling/// convertToNonSPOpcode - Change the opcode to the non-SP version, because
3767a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling/// we're replacing the frame index with a non-SP register.
3777a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendlingstatic unsigned convertToNonSPOpcode(unsigned Opcode) {
3787a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  switch (Opcode) {
3797a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  case ARM::tLDRspi:
3805a54516adf2b15fa337445d327ec3ad9bd1e3648Bill Wendling  case ARM::tRestore:           // FIXME: Should this opcode be here?
3817a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    return ARM::tLDRi;
3827a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
3837a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  case ARM::tSTRspi:
3845a54516adf2b15fa337445d327ec3ad9bd1e3648Bill Wendling  case ARM::tSpill:             // FIXME: Should this opcode be here?
3857a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    return ARM::tSTRi;
3867a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  }
3877a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
3887a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  return Opcode;
3897a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling}
3907a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
39174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool Thumb1RegisterInfo::
39274d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachrewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
39374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                  unsigned FrameReg, int &Offset,
39474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                  const ARMBaseInstrInfo &TII) const {
395a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  MachineInstr &MI = *II;
396a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  MachineBasicBlock &MBB = *MI.getParent();
397a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  DebugLoc dl = MI.getDebugLoc();
398a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Opcode = MI.getOpcode();
399a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  const TargetInstrDesc &Desc = MI.getDesc();
400a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
401a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
402a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (Opcode == ARM::tADDrSPi) {
40374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    Offset += MI.getOperand(FrameRegIdx+1).getImm();
404a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
405a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Can't use tADDrSPi if it's based off the frame pointer.
406a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned NumBits = 0;
407a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Scale = 1;
408a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (FrameReg != ARM::SP) {
409a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Opcode = ARM::tADDi3;
410446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      MI.setDesc(TII.get(Opcode));
411a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      NumBits = 3;
412a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    } else {
413a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      NumBits = 8;
414a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Scale = 4;
415a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      assert((Offset & 3) == 0 &&
416a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov             "Thumb add/sub sp, #imm immediate must be multiple of 4!");
417a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
418a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
41935f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen    unsigned PredReg;
42035f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen    if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) {
421a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Turn it into a move.
422d83360694a6d82772cf31a0be8a64570c2e5cb88Evan Cheng      MI.setDesc(TII.get(ARM::tMOVgpr2tgpr));
42374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
42435f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen      // Remove offset and remaining explicit predicate operands.
42574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      do MI.RemoveOperand(FrameRegIdx+1);
42674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      while (MI.getNumOperands() > FrameRegIdx+1 &&
42774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach             (!MI.getOperand(FrameRegIdx+1).isReg() ||
42874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach              !MI.getOperand(FrameRegIdx+1).isImm()));
42974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      return true;
430a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
431a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
432a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Common case: small offset, fits into instruction.
433a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Mask = (1 << NumBits) - 1;
434a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (((Offset / Scale) & ~Mask) == 0) {
435a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Replace the FrameIndex with sp / fp
436446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      if (Opcode == ARM::tADDi3) {
43774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        removeOperands(MI, FrameRegIdx);
438446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng        MachineInstrBuilder MIB(&MI);
439b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng        AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg)
440f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng                       .addImm(Offset / Scale));
441446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      } else {
44274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
44374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset / Scale);
444446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      }
44574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      return true;
446a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
447a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
448a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned DestReg = MI.getOperand(0).getReg();
449a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Bytes = (Offset > 0) ? Offset : -Offset;
450a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned NumMIs = calcNumMI(Opcode, 0, Bytes, NumBits, Scale);
451a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // MI would expand into a large number of instructions. Don't try to
452a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // simplify the immediate.
453a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (NumMIs > 2) {
45457caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov      emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII,
45557caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                *this);
456a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      MBB.erase(II);
45774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      return true;
458a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
459a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
460a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (Offset > 0) {
461a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Translate r0 = add sp, imm to
462a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // r0 = add sp, 255*4
463a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // r0 = add r0, (imm - 255*4)
464446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      if (Opcode == ARM::tADDi3) {
46574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        removeOperands(MI, FrameRegIdx);
466446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng        MachineInstrBuilder MIB(&MI);
467b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng        AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg).addImm(Mask));
468446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      } else {
46974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
47074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Mask);
471446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      }
472a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Offset = (Offset - Mask * Scale);
4737896c9f436a4eda5ec15e882a7505ba482a2fcd0Chris Lattner      MachineBasicBlock::iterator NII = llvm::next(II);
47457caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov      emitThumbRegPlusImmediate(MBB, NII, dl, DestReg, DestReg, Offset, TII,
47557caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                *this);
476a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    } else {
477a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Translate r0 = add sp, -imm to
478a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // r0 = -imm (this is then translated into a series of instructons)
479a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // r0 = add r0, sp
480a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      emitThumbConstant(MBB, II, DestReg, Offset, TII, *this, dl);
481bae20a6353583089224b94280a2dd69805dca247Evan Cheng
482a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      MI.setDesc(TII.get(ARM::tADDhirr));
48374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false, false, true);
48474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      MI.getOperand(FrameRegIdx+1).ChangeToRegister(FrameReg, false);
485bae20a6353583089224b94280a2dd69805dca247Evan Cheng      if (Opcode == ARM::tADDi3) {
486bae20a6353583089224b94280a2dd69805dca247Evan Cheng        MachineInstrBuilder MIB(&MI);
487bae20a6353583089224b94280a2dd69805dca247Evan Cheng        AddDefaultPred(MIB);
488bae20a6353583089224b94280a2dd69805dca247Evan Cheng      }
489a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
49074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    return true;
491a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  } else {
4927a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    if (AddrMode != ARMII::AddrModeT1_s)
493c23197a26f34f559ea9797de51e187087c039c42Torok Edwin      llvm_unreachable("Unsupported addressing mode!");
4947a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
4957a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    unsigned ImmIdx = FrameRegIdx + 1;
4967a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    int InstrOffs = MI.getOperand(ImmIdx).getImm();
4977a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5;
4987a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    unsigned Scale = 4;
499a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
500a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Offset += InstrOffs * Scale;
5017a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!");
502a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
503a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Common case: small offset, fits into instruction.
504a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    MachineOperand &ImmOp = MI.getOperand(ImmIdx);
505a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    int ImmedOffset = Offset / Scale;
506a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Mask = (1 << NumBits) - 1;
5077a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
508a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if ((unsigned)Offset <= Mask * Scale) {
5097a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      // Replace the FrameIndex with the frame register (e.g., sp).
51074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
511a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ImmOp.ChangeToImmediate(ImmedOffset);
5127a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
5137a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      // If we're using a register where sp was stored, convert the instruction
5147a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      // to the non-SP version.
5157a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      unsigned NewOpc = convertToNonSPOpcode(Opcode);
5167a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      if (NewOpc != Opcode && FrameReg != ARM::SP)
5177a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling        MI.setDesc(TII.get(NewOpc));
5187a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
51974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      return true;
520a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
521a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
5227a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    NumBits = 5;
5237a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    Mask = (1 << NumBits) - 1;
5247a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
525a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // If this is a thumb spill / restore, we will be using a constpool load to
526a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // materialize the offset.
5277a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    if (Opcode == ARM::tRestore || Opcode == ARM::tSpill) {
528a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ImmOp.ChangeToImmediate(0);
5297a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    } else {
530a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
531a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ImmedOffset = ImmedOffset & Mask;
532a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ImmOp.ChangeToImmediate(ImmedOffset);
5337a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      Offset &= ~(Mask * Scale);
534a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
535a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
5367a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
53774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  return Offset == 0;
53874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach}
53974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
54074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachvoid
54174d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I,
54274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                      unsigned BaseReg, int64_t Offset) const {
54374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  MachineInstr &MI = *I;
54474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  int Off = Offset; // ARM doesn't need the general 64-bit offsets
54574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned i = 0;
54674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
54774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  while (!MI.getOperand(i).isFI()) {
54874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    ++i;
54974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
55074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
55174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  bool Done = false;
55274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII);
55374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  assert (Done && "Unable to resolve frame index!");
55474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach}
55574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
55674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// saveScavengerRegister - Spill the register so it can be used by the
55774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// register scavenger. Return true.
55874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool
55974d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB,
56074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                          MachineBasicBlock::iterator I,
56174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                          MachineBasicBlock::iterator &UseMI,
56274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                          const TargetRegisterClass *RC,
56374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                          unsigned Reg) const {
56474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // Thumb1 can't use the emergency spill slot on the stack because
56574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // ldr/str immediate offsets must be positive, and if we're referencing
56674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // off the frame pointer (if, for example, there are alloca() calls in
56774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // the function, the offset will be negative. Use R12 instead since that's
56874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // a call clobbered register that we know won't be used in Thumb1 mode.
56974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  DebugLoc DL;
57074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  BuildMI(MBB, I, DL, TII.get(ARM::tMOVtgpr2gpr)).
57174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    addReg(ARM::R12, RegState::Define).addReg(Reg, RegState::Kill);
57274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
57374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // The UseMI is where we would like to restore the register. If there's
57474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // interference with R12 before then, however, we'll need to restore it
57574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // before that instead and adjust the UseMI.
57674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  bool done = false;
57774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) {
57874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    if (II->isDebugValue())
57974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      continue;
58074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    // If this instruction affects R12, adjust our restore point.
58174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) {
58274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      const MachineOperand &MO = II->getOperand(i);
58374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      if (!MO.isReg() || MO.isUndef() || !MO.getReg() ||
58474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach          TargetRegisterInfo::isVirtualRegister(MO.getReg()))
58574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        continue;
58674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      if (MO.getReg() == ARM::R12) {
58774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        UseMI = II;
58874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        done = true;
58974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        break;
59074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      }
59174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    }
59274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
59374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // Restore the register from R12
59474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVgpr2tgpr)).
59574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill);
59674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
59774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  return true;
59874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach}
59974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
600fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbachvoid
60174d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
602fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach                                        int SPAdj, RegScavenger *RS) const {
60374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned VReg = 0;
60474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned i = 0;
60574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  MachineInstr &MI = *II;
60674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  MachineBasicBlock &MBB = *MI.getParent();
60774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  MachineFunction &MF = *MBB.getParent();
60874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
60974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  DebugLoc dl = MI.getDebugLoc();
61074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
61174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  while (!MI.getOperand(i).isFI()) {
61274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    ++i;
61374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
61474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
61574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
61674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned FrameReg = ARM::SP;
61774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  int FrameIndex = MI.getOperand(i).getIndex();
61874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
61974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach               MF.getFrameInfo()->getStackSize() + SPAdj;
62074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
621ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach  if (AFI->isGPRCalleeSavedArea1Frame(FrameIndex))
622ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach    Offset -= AFI->getGPRCalleeSavedArea1Offset();
623ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach  else if (AFI->isGPRCalleeSavedArea2Frame(FrameIndex))
624ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach    Offset -= AFI->getGPRCalleeSavedArea2Offset();
62574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  else if (MF.getFrameInfo()->hasVarSizedObjects()) {
62616c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov    assert(SPAdj == 0 && MF.getTarget().getFrameLowering()->hasFP(MF) &&
6277920d96964d707a3af85332c98d95b2fabc3d5c9Benjamin Kramer           "Unexpected");
62874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    // There are alloca()'s in this function, must reference off the frame
62965482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach    // pointer or base pointer instead.
63065482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach    if (!hasBasePointer(MF)) {
63165482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach      FrameReg = getFrameRegister(MF);
63265482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach      Offset -= AFI->getFramePtrSpillOffset();
63365482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach    } else
63465482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach      FrameReg = BasePtr;
63574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
63674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
63774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // Special handling of dbg_value instructions.
63874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  if (MI.isDebugValue()) {
63974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    MI.getOperand(i).  ChangeToRegister(FrameReg, false /*isDef*/);
64074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    MI.getOperand(i+1).ChangeToImmediate(Offset);
641fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach    return;
64274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
64374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
64474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // Modify MI as necessary to handle as much of 'Offset' as possible
64574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  assert(AFI->isThumbFunction() &&
64674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach         "This eliminateFrameIndex only supports Thumb1!");
64774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  if (rewriteFrameIndex(MI, i, FrameReg, Offset, TII))
648fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach    return;
649a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
650a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  // If we get here, the immediate doesn't fit into the instruction.  We folded
651a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  // as much as possible above, handle the rest, providing a register that is
652a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  // SP+LargeImm.
653a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  assert(Offset && "This code isn't needed if offset already handled!");
654a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
65574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned Opcode = MI.getOpcode();
65674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  const TargetInstrDesc &Desc = MI.getDesc();
65774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
658446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  // Remove predicate first.
659446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  int PIdx = MI.findFirstPredOperandIdx();
660446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  if (PIdx != -1)
661446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    removeOperands(MI, PIdx);
662446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
663a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (Desc.mayLoad()) {
664a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Use the destination register to materialize sp + offset.
665a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned TmpReg = MI.getOperand(0).getReg();
666a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    bool UseRR = false;
667a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (Opcode == ARM::tRestore) {
668a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      if (FrameReg == ARM::SP)
6693daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov        emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg,
6703daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                 Offset, false, TII, *this);
671a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      else {
672378445303b10b092a898a75131141a8259cff50bEvan Cheng        emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset);
673a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        UseRR = true;
674a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      }
675446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    } else {
67657caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov      emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII,
67757caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                *this);
678446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    }
679446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
6806e90ce21cc2b0627ee9219e3fb0cf808f2b73328Eric Christopher    MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi));
681a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    MI.getOperand(i).ChangeToRegister(TmpReg, false, false, true);
682a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (UseRR)
6835f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach      // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
6845f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach      // register. The offset is already handled in the vreg value.
6855f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach      MI.getOperand(i+1).ChangeToRegister(FrameReg, false, false, false);
686a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  } else if (Desc.mayStore()) {
687b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach      VReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass);
6883d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach      bool UseRR = false;
689b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach
6903d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach      if (Opcode == ARM::tSpill) {
6913d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach        if (FrameReg == ARM::SP)
6923daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov          emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg,
6933daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                   Offset, false, TII, *this);
6943d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach        else {
695b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach          emitLoadConstPool(MBB, II, dl, VReg, 0, Offset);
6963d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach          UseRR = true;
6973d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach        }
6983d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach      } else
69957caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov        emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII,
70057caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                  *this);
7016e90ce21cc2b0627ee9219e3fb0cf808f2b73328Eric Christopher      MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi));
702b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach      MI.getOperand(i).ChangeToRegister(VReg, false, false, true);
7035f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach      if (UseRR)
7045f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach        // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
7055f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach        // register. The offset is already handled in the vreg value.
7065f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach        MI.getOperand(i+1).ChangeToRegister(FrameReg, false, false, false);
707f4caf69720d807573c50d41aa06bcec1c99bdbbdBill Wendling  } else {
708a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    assert(false && "Unexpected opcode!");
709f4caf69720d807573c50d41aa06bcec1c99bdbbdBill Wendling  }
710446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
711446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  // Add predicate back if it's needed.
712446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  if (MI.getDesc().isPredicable()) {
713446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    MachineInstrBuilder MIB(&MI);
714446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    AddDefaultPred(MIB);
715446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  }
716a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
717