Thumb1RegisterInfo.cpp revision e53abc20724ddde4e91467671328b531361a734f
131d157ae1ac2cd9c787dc3c1d28e64c682803844Jia Liu//===-- Thumb1RegisterInfo.cpp - Thumb-1 Register Information -------------===//
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
15c1f6f42049696e7357fb4837e1b25dabbaed3fe6Craig Topper#include "Thumb1RegisterInfo.h"
16a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARM.h"
1777521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin#include "ARMBaseInstrInfo.h"
18a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMMachineFunctionInfo.h"
19a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMSubtarget.h"
20ee04a6d3a40c3017124e3fd89a0db473a2824498Evan Cheng#include "MCTargetDesc/ARMAddressingModes.h"
21a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineConstantPool.h"
22a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineFrameInfo.h"
23a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineFunction.h"
24a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineInstrBuilder.h"
25a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineRegisterInfo.h"
260f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen#include "llvm/CodeGen/RegisterScavenging.h"
270b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Constants.h"
280b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DerivedTypes.h"
290b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Function.h"
300b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/LLVMContext.h"
314e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach#include "llvm/Support/CommandLine.h"
32ab7c09b6b6f4516a631fd6788918c237c83939afTorok Edwin#include "llvm/Support/ErrorHandling.h"
33dac237e18209b697a8ba122d0ddd9cad4dfba1f8Torok Edwin#include "llvm/Support/raw_ostream.h"
34d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Target/TargetFrameLowering.h"
35d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Target/TargetMachine.h"
36a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
378c407d45964fbba19719be555324f247e4fb14e1Dan Gohmannamespace llvm {
384e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbachextern cl::opt<bool> ReuseFrameIndexVals;
398c407d45964fbba19719be555324f247e4fb14e1Dan Gohman}
408c407d45964fbba19719be555324f247e4fb14e1Dan Gohman
418c407d45964fbba19719be555324f247e4fb14e1Dan Gohmanusing namespace llvm;
424e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach
4357148c166ab232191098492633c924fad9c44ef3Bill WendlingThumb1RegisterInfo::Thumb1RegisterInfo(const ARMSubtarget &sti)
4457148c166ab232191098492633c924fad9c44ef3Bill Wendling  : ARMBaseRegisterInfo(sti) {
45a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
46a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
47c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesenconst TargetRegisterClass*
48c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund OlesenThumb1RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC)
49c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen                                                                         const {
50fa226bccaa90c520cac154df74069bbabb976eabJakob Stoklund Olesen  if (ARM::tGPRRegClass.hasSubClassEq(RC))
51420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper    return &ARM::tGPRRegClass;
52c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen  return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC);
53c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen}
54c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen
551db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesenconst TargetRegisterClass *
56397fc4874efe9c17e737d4c5c50bd19dc3bf27f5Jakob Stoklund OlesenThumb1RegisterInfo::getPointerRegClass(const MachineFunction &MF, unsigned Kind)
57397fc4874efe9c17e737d4c5c50bd19dc3bf27f5Jakob Stoklund Olesen                                                                         const {
58420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper  return &ARM::tGPRRegClass;
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();
7257148c166ab232191098492633c924fad9c44ef3Bill Wendling  const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
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!");
113420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper      LdReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);
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;
185a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
186a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (DestReg == BaseReg && BaseReg == ARM::SP) {
187a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!");
188a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumBits = 7;
189a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Scale = 4;
190a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
191a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    isTwoAddr = true;
192a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  } else if (!isSub && BaseReg == ARM::SP) {
193a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r1 = add sp, 403
194a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // =>
195a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r1 = add sp, 100 * 4
196a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r1 = add r1, 3
197a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (!isMul4) {
198a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Bytes &= ~3;
199a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ExtraOpc = ARM::tADDi3;
200a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
201a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumBits = 8;
202a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Scale = 4;
203a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Opc = ARM::tADDrSPi;
204a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  } else {
205a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // sp = sub sp, c
206a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r1 = sub sp, c
207a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // r8 = sub sp, c
208a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (DestReg != BaseReg)
209a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      DstNotEqBase = true;
210a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    NumBits = 8;
211f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng    if (DestReg == ARM::SP) {
212f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
213f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!");
214f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      NumBits = 7;
215f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      Scale = 4;
216f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng    } else {
217f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
218f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng      NumBits = 8;
2195b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach      NeedCC = true;
220f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng    }
221a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    isTwoAddr = true;
222a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
223a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
224a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale);
225a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2;
226a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (NumMIs > Threshold) {
227a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // This will expand into too many instructions. Load the immediate from a
228a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // constpool entry.
2293daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov    emitThumbRegPlusImmInReg(MBB, MBBI, dl,
2303daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                             DestReg, BaseReg, NumBytes, true,
2313daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                             TII, MRI, MIFlags);
232a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    return;
233a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
234a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
235a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (DstNotEqBase) {
23655ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov    if (isARMLowRegister(DestReg) && isARMLowRegister(BaseReg)) {
237a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // If both are low registers, emit DestReg = add BaseReg, max(Imm, 7)
238a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      unsigned Chunk = (1 << 3) - 1;
239a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
240a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Bytes -= ThisVal;
241e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng      const MCInstrDesc &MCID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3);
242446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      const MachineInstrBuilder MIB =
2434372ca6fe4119d708d43d9c9ac3feafc7607952aJim Grosbach        AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)
2444372ca6fe4119d708d43d9c9ac3feafc7607952aJim Grosbach                         .setMIFlags(MIFlags));
245446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal));
246a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    } else {
24763b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach      AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
24863b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach        .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);
2655b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach      MIB = AddDefaultPred(MIB);
2663daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov      MIB.setMIFlags(MIFlags);
2678884148b8e8f19d5484e735618cf188cfa02c626Jim Grosbach    } else {
268a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      bool isKill = BaseReg != ARM::SP;
269446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
270446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      if (NeedCC)
271b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng        MIB = AddDefaultT1CC(MIB);
272446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal);
2735b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach      MIB = AddDefaultPred(MIB);
2743daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov      MIB.setMIFlags(MIFlags);
275a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
2763daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov      BaseReg = DestReg;
277a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      if (Opc == ARM::tADDrSPi) {
278a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        // r4 = add sp, imm
279a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        // r4 = add r4, imm
280a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        // ...
281a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        NumBits = 8;
282a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        Scale = 1;
283a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        Chunk = ((1 << NumBits) - 1) * Scale;
284a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
2855b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach        NeedCC = isTwoAddr = true;
286a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      }
287a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
288a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
289a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
290446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  if (ExtraOpc) {
291e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng    const MCInstrDesc &MCID = TII.get(ExtraOpc);
292e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng    AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg))
293446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng                   .addReg(DestReg, RegState::Kill)
2943daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                   .addImm(((unsigned)NumBytes) & 3)
2953daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                   .setMIFlags(MIFlags));
296446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  }
297a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
298a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
299a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbConstant - Emit a series of instructions to materialize a
300a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constant.
301a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic void emitThumbConstant(MachineBasicBlock &MBB,
302a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              MachineBasicBlock::iterator &MBBI,
303a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              unsigned DestReg, int Imm,
304a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              const TargetInstrInfo &TII,
305b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin                              const Thumb1RegisterInfo& MRI,
306a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov                              DebugLoc dl) {
307a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  bool isSub = Imm < 0;
308a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (isSub) Imm = -Imm;
309a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
310a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  int Chunk = (1 << 8) - 1;
311a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  int ThisVal = (Imm > Chunk) ? Chunk : Imm;
312a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  Imm -= ThisVal;
313b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng  AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8),
314b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng                                        DestReg))
315446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng                 .addImm(ThisVal));
316a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (Imm > 0)
31757caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov    emitThumbRegPlusImmediate(MBB, MBBI, dl, DestReg, DestReg, Imm, TII, MRI);
318446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  if (isSub) {
319e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng    const MCInstrDesc &MCID = TII.get(ARM::tRSB);
320e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng    AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg))
321446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng                   .addReg(DestReg, RegState::Kill));
322446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  }
323446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng}
324446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
325446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Chengstatic void removeOperands(MachineInstr &MI, unsigned i) {
326446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  unsigned Op = i;
327446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  for (unsigned e = MI.getNumOperands(); i != e; ++i)
328446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    MI.RemoveOperand(Op);
329a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
330a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
3317a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling/// convertToNonSPOpcode - Change the opcode to the non-SP version, because
3327a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling/// we're replacing the frame index with a non-SP register.
3337a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendlingstatic unsigned convertToNonSPOpcode(unsigned Opcode) {
3347a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  switch (Opcode) {
3357a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  case ARM::tLDRspi:
3367a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    return ARM::tLDRi;
3377a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
3387a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  case ARM::tSTRspi:
3397a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    return ARM::tSTRi;
3407a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  }
3417a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
3427a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling  return Opcode;
3437a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling}
3447a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
34574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool Thumb1RegisterInfo::
34674d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachrewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
34774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                  unsigned FrameReg, int &Offset,
34874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                  const ARMBaseInstrInfo &TII) const {
349a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  MachineInstr &MI = *II;
350a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  MachineBasicBlock &MBB = *MI.getParent();
351a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  DebugLoc dl = MI.getDebugLoc();
35237a942cd52725b1d390989a8267a764b42fcb5d3Jakob Stoklund Olesen  MachineInstrBuilder MIB(*MBB.getParent(), &MI);
353a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned Opcode = MI.getOpcode();
354e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  const MCInstrDesc &Desc = MI.getDesc();
355a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
356a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
357a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  if (Opcode == ARM::tADDrSPi) {
35874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    Offset += MI.getOperand(FrameRegIdx+1).getImm();
359a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
360a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Can't use tADDrSPi if it's based off the frame pointer.
361a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned NumBits = 0;
362a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Scale = 1;
363a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (FrameReg != ARM::SP) {
364a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Opcode = ARM::tADDi3;
365a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      NumBits = 3;
366a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    } else {
367a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      NumBits = 8;
368a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Scale = 4;
369a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      assert((Offset & 3) == 0 &&
370a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov             "Thumb add/sub sp, #imm immediate must be multiple of 4!");
371a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
372a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
37335f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen    unsigned PredReg;
37435f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen    if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) {
375a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Turn it into a move.
3762a7b41ba4d3eb3c6003f6768dc20b28d83eac265Jim Grosbach      MI.setDesc(TII.get(ARM::tMOVr));
37774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
3785b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach      // Remove offset
37963b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach      MI.RemoveOperand(FrameRegIdx+1);
38074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      return true;
381a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
382a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
383a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Common case: small offset, fits into instruction.
384a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Mask = (1 << NumBits) - 1;
385a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (((Offset / Scale) & ~Mask) == 0) {
386a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Replace the FrameIndex with sp / fp
387446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      if (Opcode == ARM::tADDi3) {
3885b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach        MI.setDesc(TII.get(Opcode));
38974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        removeOperands(MI, FrameRegIdx);
390b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng        AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg)
391f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng                       .addImm(Offset / Scale));
392446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      } else {
39374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
39474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset / Scale);
395446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      }
39674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      return true;
397a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
398a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
399a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned DestReg = MI.getOperand(0).getReg();
400a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Bytes = (Offset > 0) ? Offset : -Offset;
401a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned NumMIs = calcNumMI(Opcode, 0, Bytes, NumBits, Scale);
402a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // MI would expand into a large number of instructions. Don't try to
403a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // simplify the immediate.
404a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (NumMIs > 2) {
40557caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov      emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII,
40657caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                *this);
407a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      MBB.erase(II);
40874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      return true;
409a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
410a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
411a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (Offset > 0) {
412a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Translate r0 = add sp, imm to
413a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // r0 = add sp, 255*4
414a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // r0 = add r0, (imm - 255*4)
415446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      if (Opcode == ARM::tADDi3) {
41629b9d7e4ea7521be25bccdb66ecd9c9df5ed8b4bChad Rosier        MI.setDesc(TII.get(Opcode));
41774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        removeOperands(MI, FrameRegIdx);
418b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng        AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg).addImm(Mask));
419446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      } else {
42074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
42174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Mask);
422446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng      }
423a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      Offset = (Offset - Mask * Scale);
4247896c9f436a4eda5ec15e882a7505ba482a2fcd0Chris Lattner      MachineBasicBlock::iterator NII = llvm::next(II);
42557caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov      emitThumbRegPlusImmediate(MBB, NII, dl, DestReg, DestReg, Offset, TII,
42657caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                *this);
427a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    } else {
428a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Translate r0 = add sp, -imm to
4293f4f420ab7acb10221ba971543a7eed5489fb626Robert Wilhelm      // r0 = -imm (this is then translated into a series of instructions)
430a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // r0 = add r0, sp
431a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      emitThumbConstant(MBB, II, DestReg, Offset, TII, *this, dl);
432bae20a6353583089224b94280a2dd69805dca247Evan Cheng
433a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      MI.setDesc(TII.get(ARM::tADDhirr));
43474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false, false, true);
43574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      MI.getOperand(FrameRegIdx+1).ChangeToRegister(FrameReg, false);
436a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
43774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    return true;
438a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  } else {
4397a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    if (AddrMode != ARMII::AddrModeT1_s)
440c23197a26f34f559ea9797de51e187087c039c42Torok Edwin      llvm_unreachable("Unsupported addressing mode!");
4417a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
4427a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    unsigned ImmIdx = FrameRegIdx + 1;
4437a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    int InstrOffs = MI.getOperand(ImmIdx).getImm();
4447a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5;
4457a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    unsigned Scale = 4;
446a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
447a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    Offset += InstrOffs * Scale;
4487a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!");
449a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
450a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Common case: small offset, fits into instruction.
451a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    MachineOperand &ImmOp = MI.getOperand(ImmIdx);
452a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    int ImmedOffset = Offset / Scale;
453a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned Mask = (1 << NumBits) - 1;
4547a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
455a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if ((unsigned)Offset <= Mask * Scale) {
4567a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      // Replace the FrameIndex with the frame register (e.g., sp).
45774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
458a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ImmOp.ChangeToImmediate(ImmedOffset);
4597a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
4607a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      // If we're using a register where sp was stored, convert the instruction
4617a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      // to the non-SP version.
4627a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      unsigned NewOpc = convertToNonSPOpcode(Opcode);
4637a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      if (NewOpc != Opcode && FrameReg != ARM::SP)
4647a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling        MI.setDesc(TII.get(NewOpc));
4657a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
46674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      return true;
467a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
468a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
4697a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    NumBits = 5;
4707a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    Mask = (1 << NumBits) - 1;
4717a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
472a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // If this is a thumb spill / restore, we will be using a constpool load to
473a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // materialize the offset.
47474472b4bf963c424da04f42dffdb94c85ef964bcJim Grosbach    if (Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {
475a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ImmOp.ChangeToImmediate(0);
4767a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling    } else {
477a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
478a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ImmedOffset = ImmedOffset & Mask;
479a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      ImmOp.ChangeToImmediate(ImmedOffset);
4807a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling      Offset &= ~(Mask * Scale);
481a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    }
482a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  }
4837a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling
48474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  return Offset == 0;
48574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach}
48674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
48774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachvoid
48874d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I,
48974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                      unsigned BaseReg, int64_t Offset) const {
49074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  MachineInstr &MI = *I;
49157148c166ab232191098492633c924fad9c44ef3Bill Wendling  const ARMBaseInstrInfo &TII =
49257148c166ab232191098492633c924fad9c44ef3Bill Wendling    *static_cast<const ARMBaseInstrInfo*>(
49357148c166ab232191098492633c924fad9c44ef3Bill Wendling      MI.getParent()->getParent()->getTarget().getInstrInfo());
49474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  int Off = Offset; // ARM doesn't need the general 64-bit offsets
49574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned i = 0;
49674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
49774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  while (!MI.getOperand(i).isFI()) {
49874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    ++i;
49974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
50074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
5011f6a329f79b3568d379142f921f59c4143ddaa14Duncan Sands  bool Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII);
50274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  assert (Done && "Unable to resolve frame index!");
5031f6a329f79b3568d379142f921f59c4143ddaa14Duncan Sands  (void)Done;
50474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach}
50574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
50674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// saveScavengerRegister - Spill the register so it can be used by the
50774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// register scavenger. Return true.
50874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool
50974d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB,
51074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                          MachineBasicBlock::iterator I,
51174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                          MachineBasicBlock::iterator &UseMI,
51274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                          const TargetRegisterClass *RC,
51374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach                                          unsigned Reg) const {
51474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // Thumb1 can't use the emergency spill slot on the stack because
51574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // ldr/str immediate offsets must be positive, and if we're referencing
51674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // off the frame pointer (if, for example, there are alloca() calls in
51774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // the function, the offset will be negative. Use R12 instead since that's
51874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // a call clobbered register that we know won't be used in Thumb1 mode.
51957148c166ab232191098492633c924fad9c44ef3Bill Wendling  const TargetInstrInfo &TII = *MBB.getParent()->getTarget().getInstrInfo();
52074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  DebugLoc DL;
5212a7b41ba4d3eb3c6003f6768dc20b28d83eac265Jim Grosbach  AddDefaultPred(BuildMI(MBB, I, DL, TII.get(ARM::tMOVr))
52263b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach    .addReg(ARM::R12, RegState::Define)
52363b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach    .addReg(Reg, RegState::Kill));
52474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
52574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // The UseMI is where we would like to restore the register. If there's
52674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // interference with R12 before then, however, we'll need to restore it
52774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // before that instead and adjust the UseMI.
52874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  bool done = false;
52974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) {
53074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    if (II->isDebugValue())
53174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      continue;
53274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    // If this instruction affects R12, adjust our restore point.
53374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) {
53474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      const MachineOperand &MO = II->getOperand(i);
535b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen      if (MO.isRegMask() && MO.clobbersPhysReg(ARM::R12)) {
536b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen        UseMI = II;
537b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen        done = true;
538b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen        break;
539b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen      }
54074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      if (!MO.isReg() || MO.isUndef() || !MO.getReg() ||
54174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach          TargetRegisterInfo::isVirtualRegister(MO.getReg()))
54274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        continue;
54374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      if (MO.getReg() == ARM::R12) {
54474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        UseMI = II;
54574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        done = true;
54674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach        break;
54774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach      }
54874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    }
54974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
55074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // Restore the register from R12
5512a7b41ba4d3eb3c6003f6768dc20b28d83eac265Jim Grosbach  AddDefaultPred(BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVr)).
55263b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach    addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill));
55374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
55474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  return true;
55574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach}
55674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
557fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbachvoid
55874d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
559108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier                                        int SPAdj, unsigned FIOperandNum,
560108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier                                        RegScavenger *RS) const {
56174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned VReg = 0;
56274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  MachineInstr &MI = *II;
56374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  MachineBasicBlock &MBB = *MI.getParent();
56474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  MachineFunction &MF = *MBB.getParent();
56557148c166ab232191098492633c924fad9c44ef3Bill Wendling  const ARMBaseInstrInfo &TII =
56657148c166ab232191098492633c924fad9c44ef3Bill Wendling    *static_cast<const ARMBaseInstrInfo*>(MF.getTarget().getInstrInfo());
56774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
56874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  DebugLoc dl = MI.getDebugLoc();
56937a942cd52725b1d390989a8267a764b42fcb5d3Jakob Stoklund Olesen  MachineInstrBuilder MIB(*MBB.getParent(), &MI);
57074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
57174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned FrameReg = ARM::SP;
572108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
57374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
57474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach               MF.getFrameInfo()->getStackSize() + SPAdj;
57574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
576e53abc20724ddde4e91467671328b531361a734fTim Northover  if (MF.getFrameInfo()->hasVarSizedObjects()) {
57716c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov    assert(SPAdj == 0 && MF.getTarget().getFrameLowering()->hasFP(MF) &&
5787920d96964d707a3af85332c98d95b2fabc3d5c9Benjamin Kramer           "Unexpected");
57974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach    // There are alloca()'s in this function, must reference off the frame
58065482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach    // pointer or base pointer instead.
58165482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach    if (!hasBasePointer(MF)) {
58265482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach      FrameReg = getFrameRegister(MF);
58365482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach      Offset -= AFI->getFramePtrSpillOffset();
58465482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach    } else
58565482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach      FrameReg = BasePtr;
58674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
58774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
5880f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen  // PEI::scavengeFrameVirtualRegs() cannot accurately track SPAdj because the
5890f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen  // call frame setup/destroy instructions have already been eliminated.  That
5900f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen  // means the stack pointer cannot be used to access the emergency spill slot
5910f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen  // when !hasReservedCallFrame().
5920f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen#ifndef NDEBUG
593dc3beb90178fc316f63790812b22201884eaa017Hal Finkel  if (RS && FrameReg == ARM::SP && RS->isScavengingFrameIndex(FrameIndex)){
5940f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen    assert(MF.getTarget().getFrameLowering()->hasReservedCallFrame(MF) &&
5950f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen           "Cannot use SP to access the emergency spill slot in "
5960f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen           "functions without a reserved call frame");
5970f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen    assert(!MF.getFrameInfo()->hasVarSizedObjects() &&
5980f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen           "Cannot use SP to access the emergency spill slot in "
5990f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen           "functions with variable sized frame objects");
6000f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen  }
6010f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen#endif // NDEBUG
6020f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen
60374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // Special handling of dbg_value instructions.
60474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  if (MI.isDebugValue()) {
605108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier    MI.getOperand(FIOperandNum).  ChangeToRegister(FrameReg, false /*isDef*/);
606108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier    MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
607fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach    return;
60874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  }
60974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
61074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  // Modify MI as necessary to handle as much of 'Offset' as possible
61174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  assert(AFI->isThumbFunction() &&
61274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach         "This eliminateFrameIndex only supports Thumb1!");
613108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier  if (rewriteFrameIndex(MI, FIOperandNum, FrameReg, Offset, TII))
614fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach    return;
615a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
616a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  // If we get here, the immediate doesn't fit into the instruction.  We folded
617a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  // as much as possible above, handle the rest, providing a register that is
618a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  // SP+LargeImm.
619a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov  assert(Offset && "This code isn't needed if offset already handled!");
620a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov
62174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach  unsigned Opcode = MI.getOpcode();
62274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach
623446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  // Remove predicate first.
624446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  int PIdx = MI.findFirstPredOperandIdx();
625446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  if (PIdx != -1)
626446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    removeOperands(MI, PIdx);
627446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
6285a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng  if (MI.mayLoad()) {
629a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    // Use the destination register to materialize sp + offset.
630a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    unsigned TmpReg = MI.getOperand(0).getReg();
631a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    bool UseRR = false;
63274472b4bf963c424da04f42dffdb94c85ef964bcJim Grosbach    if (Opcode == ARM::tLDRspi) {
633a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      if (FrameReg == ARM::SP)
6343daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov        emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg,
6353daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                 Offset, false, TII, *this);
636a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      else {
637378445303b10b092a898a75131141a8259cff50bEvan Cheng        emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset);
638a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov        UseRR = true;
639a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov      }
640446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    } else {
64157caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov      emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII,
64257caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                *this);
643446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    }
644446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
6456e90ce21cc2b0627ee9219e3fb0cf808f2b73328Eric Christopher    MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi));
646108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier    MI.getOperand(FIOperandNum).ChangeToRegister(TmpReg, false, false, true);
647a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov    if (UseRR)
6485f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach      // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
6495f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach      // register. The offset is already handled in the vreg value.
650108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier      MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false,
651108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier                                                     false);
6525a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng  } else if (MI.mayStore()) {
653420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper      VReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);
6543d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach      bool UseRR = false;
655b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach
65674472b4bf963c424da04f42dffdb94c85ef964bcJim Grosbach      if (Opcode == ARM::tSTRspi) {
6573d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach        if (FrameReg == ARM::SP)
6583daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov          emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg,
6593daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov                                   Offset, false, TII, *this);
6603d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach        else {
661b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach          emitLoadConstPool(MBB, II, dl, VReg, 0, Offset);
6623d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach          UseRR = true;
6633d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach        }
6643d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach      } else
66557caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov        emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII,
66657caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov                                  *this);
6676e90ce21cc2b0627ee9219e3fb0cf808f2b73328Eric Christopher      MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi));
668108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier      MI.getOperand(FIOperandNum).ChangeToRegister(VReg, false, false, true);
6695f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach      if (UseRR)
6705f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach        // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
6715f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach        // register. The offset is already handled in the vreg value.
672108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier        MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false,
673108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier                                                       false);
674f4caf69720d807573c50d41aa06bcec1c99bdbbdBill Wendling  } else {
675bc2198133a1836598b54b943420748e75d5dea94Craig Topper    llvm_unreachable("Unexpected opcode!");
676f4caf69720d807573c50d41aa06bcec1c99bdbbdBill Wendling  }
677446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng
678446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng  // Add predicate back if it's needed.
67937a942cd52725b1d390989a8267a764b42fcb5d3Jakob Stoklund Olesen  if (MI.isPredicable())
680446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng    AddDefaultPred(MIB);
681a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov}
682