xref: /aosp_15_r20/external/llvm/lib/Target/ARM/ThumbRegisterInfo.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- ThumbRegisterInfo.cpp - Thumb-1 Register Information -------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file contains the Thumb-1 implementation of the TargetRegisterInfo
11*9880d681SAndroid Build Coastguard Worker // class.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #include "ThumbRegisterInfo.h"
16*9880d681SAndroid Build Coastguard Worker #include "ARMBaseInstrInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "ARMMachineFunctionInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "ARMSubtarget.h"
19*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/ARMAddressingModes.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineConstantPool.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/RegisterScavenging.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetFrameLowering.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker namespace llvm {
36*9880d681SAndroid Build Coastguard Worker extern cl::opt<bool> ReuseFrameIndexVals;
37*9880d681SAndroid Build Coastguard Worker }
38*9880d681SAndroid Build Coastguard Worker 
39*9880d681SAndroid Build Coastguard Worker using namespace llvm;
40*9880d681SAndroid Build Coastguard Worker 
ThumbRegisterInfo()41*9880d681SAndroid Build Coastguard Worker ThumbRegisterInfo::ThumbRegisterInfo() : ARMBaseRegisterInfo() {}
42*9880d681SAndroid Build Coastguard Worker 
43*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *
getLargestLegalSuperClass(const TargetRegisterClass * RC,const MachineFunction & MF) const44*9880d681SAndroid Build Coastguard Worker ThumbRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
45*9880d681SAndroid Build Coastguard Worker                                               const MachineFunction &MF) const {
46*9880d681SAndroid Build Coastguard Worker   if (!MF.getSubtarget<ARMSubtarget>().isThumb1Only())
47*9880d681SAndroid Build Coastguard Worker     return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC, MF);
48*9880d681SAndroid Build Coastguard Worker 
49*9880d681SAndroid Build Coastguard Worker   if (ARM::tGPRRegClass.hasSubClassEq(RC))
50*9880d681SAndroid Build Coastguard Worker     return &ARM::tGPRRegClass;
51*9880d681SAndroid Build Coastguard Worker   return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC, MF);
52*9880d681SAndroid Build Coastguard Worker }
53*9880d681SAndroid Build Coastguard Worker 
54*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *
getPointerRegClass(const MachineFunction & MF,unsigned Kind) const55*9880d681SAndroid Build Coastguard Worker ThumbRegisterInfo::getPointerRegClass(const MachineFunction &MF,
56*9880d681SAndroid Build Coastguard Worker                                       unsigned Kind) const {
57*9880d681SAndroid Build Coastguard Worker   if (!MF.getSubtarget<ARMSubtarget>().isThumb1Only())
58*9880d681SAndroid Build Coastguard Worker     return ARMBaseRegisterInfo::getPointerRegClass(MF, Kind);
59*9880d681SAndroid Build Coastguard Worker   return &ARM::tGPRRegClass;
60*9880d681SAndroid Build Coastguard Worker }
61*9880d681SAndroid Build Coastguard Worker 
emitThumb1LoadConstPool(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI,const DebugLoc & dl,unsigned DestReg,unsigned SubIdx,int Val,ARMCC::CondCodes Pred,unsigned PredReg,unsigned MIFlags)62*9880d681SAndroid Build Coastguard Worker static void emitThumb1LoadConstPool(MachineBasicBlock &MBB,
63*9880d681SAndroid Build Coastguard Worker                                     MachineBasicBlock::iterator &MBBI,
64*9880d681SAndroid Build Coastguard Worker                                     const DebugLoc &dl, unsigned DestReg,
65*9880d681SAndroid Build Coastguard Worker                                     unsigned SubIdx, int Val,
66*9880d681SAndroid Build Coastguard Worker                                     ARMCC::CondCodes Pred, unsigned PredReg,
67*9880d681SAndroid Build Coastguard Worker                                     unsigned MIFlags) {
68*9880d681SAndroid Build Coastguard Worker   MachineFunction &MF = *MBB.getParent();
69*9880d681SAndroid Build Coastguard Worker   const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
70*9880d681SAndroid Build Coastguard Worker   const TargetInstrInfo &TII = *STI.getInstrInfo();
71*9880d681SAndroid Build Coastguard Worker   MachineConstantPool *ConstantPool = MF.getConstantPool();
72*9880d681SAndroid Build Coastguard Worker   const Constant *C = ConstantInt::get(
73*9880d681SAndroid Build Coastguard Worker           Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val);
74*9880d681SAndroid Build Coastguard Worker   unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
75*9880d681SAndroid Build Coastguard Worker 
76*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRpci))
77*9880d681SAndroid Build Coastguard Worker     .addReg(DestReg, getDefRegState(true), SubIdx)
78*9880d681SAndroid Build Coastguard Worker     .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg)
79*9880d681SAndroid Build Coastguard Worker     .setMIFlags(MIFlags);
80*9880d681SAndroid Build Coastguard Worker }
81*9880d681SAndroid Build Coastguard Worker 
emitThumb2LoadConstPool(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI,const DebugLoc & dl,unsigned DestReg,unsigned SubIdx,int Val,ARMCC::CondCodes Pred,unsigned PredReg,unsigned MIFlags)82*9880d681SAndroid Build Coastguard Worker static void emitThumb2LoadConstPool(MachineBasicBlock &MBB,
83*9880d681SAndroid Build Coastguard Worker                                     MachineBasicBlock::iterator &MBBI,
84*9880d681SAndroid Build Coastguard Worker                                     const DebugLoc &dl, unsigned DestReg,
85*9880d681SAndroid Build Coastguard Worker                                     unsigned SubIdx, int Val,
86*9880d681SAndroid Build Coastguard Worker                                     ARMCC::CondCodes Pred, unsigned PredReg,
87*9880d681SAndroid Build Coastguard Worker                                     unsigned MIFlags) {
88*9880d681SAndroid Build Coastguard Worker   MachineFunction &MF = *MBB.getParent();
89*9880d681SAndroid Build Coastguard Worker   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
90*9880d681SAndroid Build Coastguard Worker   MachineConstantPool *ConstantPool = MF.getConstantPool();
91*9880d681SAndroid Build Coastguard Worker   const Constant *C = ConstantInt::get(
92*9880d681SAndroid Build Coastguard Worker            Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val);
93*9880d681SAndroid Build Coastguard Worker   unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
94*9880d681SAndroid Build Coastguard Worker 
95*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, MBBI, dl, TII.get(ARM::t2LDRpci))
96*9880d681SAndroid Build Coastguard Worker     .addReg(DestReg, getDefRegState(true), SubIdx)
97*9880d681SAndroid Build Coastguard Worker     .addConstantPoolIndex(Idx).addImm((int64_t)ARMCC::AL).addReg(0)
98*9880d681SAndroid Build Coastguard Worker     .setMIFlags(MIFlags);
99*9880d681SAndroid Build Coastguard Worker }
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker /// emitLoadConstPool - Emits a load from constpool to materialize the
102*9880d681SAndroid Build Coastguard Worker /// specified immediate.
emitLoadConstPool(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI,const DebugLoc & dl,unsigned DestReg,unsigned SubIdx,int Val,ARMCC::CondCodes Pred,unsigned PredReg,unsigned MIFlags) const103*9880d681SAndroid Build Coastguard Worker void ThumbRegisterInfo::emitLoadConstPool(
104*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
105*9880d681SAndroid Build Coastguard Worker     const DebugLoc &dl, unsigned DestReg, unsigned SubIdx, int Val,
106*9880d681SAndroid Build Coastguard Worker     ARMCC::CondCodes Pred, unsigned PredReg, unsigned MIFlags) const {
107*9880d681SAndroid Build Coastguard Worker   MachineFunction &MF = *MBB.getParent();
108*9880d681SAndroid Build Coastguard Worker   const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
109*9880d681SAndroid Build Coastguard Worker   if (STI.isThumb1Only()) {
110*9880d681SAndroid Build Coastguard Worker     assert((isARMLowRegister(DestReg) || isVirtualRegister(DestReg)) &&
111*9880d681SAndroid Build Coastguard Worker            "Thumb1 does not have ldr to high register");
112*9880d681SAndroid Build Coastguard Worker     return emitThumb1LoadConstPool(MBB, MBBI, dl, DestReg, SubIdx, Val, Pred,
113*9880d681SAndroid Build Coastguard Worker                                    PredReg, MIFlags);
114*9880d681SAndroid Build Coastguard Worker   }
115*9880d681SAndroid Build Coastguard Worker   return emitThumb2LoadConstPool(MBB, MBBI, dl, DestReg, SubIdx, Val, Pred,
116*9880d681SAndroid Build Coastguard Worker                                  PredReg, MIFlags);
117*9880d681SAndroid Build Coastguard Worker }
118*9880d681SAndroid Build Coastguard Worker 
119*9880d681SAndroid Build Coastguard Worker /// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize
120*9880d681SAndroid Build Coastguard Worker /// a destreg = basereg + immediate in Thumb code. Materialize the immediate
121*9880d681SAndroid Build Coastguard Worker /// in a register using mov / mvn sequences or load the immediate from a
122*9880d681SAndroid Build Coastguard Worker /// constpool entry.
emitThumbRegPlusImmInReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI,const DebugLoc & dl,unsigned DestReg,unsigned BaseReg,int NumBytes,bool CanChangeCC,const TargetInstrInfo & TII,const ARMBaseRegisterInfo & MRI,unsigned MIFlags=MachineInstr::NoFlags)123*9880d681SAndroid Build Coastguard Worker static void emitThumbRegPlusImmInReg(
124*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
125*9880d681SAndroid Build Coastguard Worker     const DebugLoc &dl, unsigned DestReg, unsigned BaseReg, int NumBytes,
126*9880d681SAndroid Build Coastguard Worker     bool CanChangeCC, const TargetInstrInfo &TII,
127*9880d681SAndroid Build Coastguard Worker     const ARMBaseRegisterInfo &MRI, unsigned MIFlags = MachineInstr::NoFlags) {
128*9880d681SAndroid Build Coastguard Worker   MachineFunction &MF = *MBB.getParent();
129*9880d681SAndroid Build Coastguard Worker   bool isHigh = !isARMLowRegister(DestReg) ||
130*9880d681SAndroid Build Coastguard Worker                 (BaseReg != 0 && !isARMLowRegister(BaseReg));
131*9880d681SAndroid Build Coastguard Worker   bool isSub = false;
132*9880d681SAndroid Build Coastguard Worker   // Subtract doesn't have high register version. Load the negative value
133*9880d681SAndroid Build Coastguard Worker   // if either base or dest register is a high register. Also, if do not
134*9880d681SAndroid Build Coastguard Worker   // issue sub as part of the sequence if condition register is to be
135*9880d681SAndroid Build Coastguard Worker   // preserved.
136*9880d681SAndroid Build Coastguard Worker   if (NumBytes < 0 && !isHigh && CanChangeCC) {
137*9880d681SAndroid Build Coastguard Worker     isSub = true;
138*9880d681SAndroid Build Coastguard Worker     NumBytes = -NumBytes;
139*9880d681SAndroid Build Coastguard Worker   }
140*9880d681SAndroid Build Coastguard Worker   unsigned LdReg = DestReg;
141*9880d681SAndroid Build Coastguard Worker   if (DestReg == ARM::SP)
142*9880d681SAndroid Build Coastguard Worker     assert(BaseReg == ARM::SP && "Unexpected!");
143*9880d681SAndroid Build Coastguard Worker   if (!isARMLowRegister(DestReg) && !MRI.isVirtualRegister(DestReg))
144*9880d681SAndroid Build Coastguard Worker     LdReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);
145*9880d681SAndroid Build Coastguard Worker 
146*9880d681SAndroid Build Coastguard Worker   if (NumBytes <= 255 && NumBytes >= 0 && CanChangeCC) {
147*9880d681SAndroid Build Coastguard Worker     AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg))
148*9880d681SAndroid Build Coastguard Worker         .addImm(NumBytes)
149*9880d681SAndroid Build Coastguard Worker         .setMIFlags(MIFlags);
150*9880d681SAndroid Build Coastguard Worker   } else if (NumBytes < 0 && NumBytes >= -255 && CanChangeCC) {
151*9880d681SAndroid Build Coastguard Worker     AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg))
152*9880d681SAndroid Build Coastguard Worker         .addImm(NumBytes)
153*9880d681SAndroid Build Coastguard Worker         .setMIFlags(MIFlags);
154*9880d681SAndroid Build Coastguard Worker     AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg))
155*9880d681SAndroid Build Coastguard Worker         .addReg(LdReg, RegState::Kill)
156*9880d681SAndroid Build Coastguard Worker         .setMIFlags(MIFlags);
157*9880d681SAndroid Build Coastguard Worker   } else
158*9880d681SAndroid Build Coastguard Worker     MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes, ARMCC::AL, 0,
159*9880d681SAndroid Build Coastguard Worker                           MIFlags);
160*9880d681SAndroid Build Coastguard Worker 
161*9880d681SAndroid Build Coastguard Worker   // Emit add / sub.
162*9880d681SAndroid Build Coastguard Worker   int Opc = (isSub) ? ARM::tSUBrr
163*9880d681SAndroid Build Coastguard Worker                     : ((isHigh || !CanChangeCC) ? ARM::tADDhirr : ARM::tADDrr);
164*9880d681SAndroid Build Coastguard Worker   MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
165*9880d681SAndroid Build Coastguard Worker   if (Opc != ARM::tADDhirr)
166*9880d681SAndroid Build Coastguard Worker     MIB = AddDefaultT1CC(MIB);
167*9880d681SAndroid Build Coastguard Worker   if (DestReg == ARM::SP || isSub)
168*9880d681SAndroid Build Coastguard Worker     MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill);
169*9880d681SAndroid Build Coastguard Worker   else
170*9880d681SAndroid Build Coastguard Worker     MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill);
171*9880d681SAndroid Build Coastguard Worker   AddDefaultPred(MIB);
172*9880d681SAndroid Build Coastguard Worker }
173*9880d681SAndroid Build Coastguard Worker 
174*9880d681SAndroid Build Coastguard Worker /// emitThumbRegPlusImmediate - Emits a series of instructions to materialize
175*9880d681SAndroid Build Coastguard Worker /// a destreg = basereg + immediate in Thumb code. Tries a series of ADDs or
176*9880d681SAndroid Build Coastguard Worker /// SUBs first, and uses a constant pool value if the instruction sequence would
177*9880d681SAndroid Build Coastguard Worker /// be too long. This is allowed to modify the condition flags.
emitThumbRegPlusImmediate(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI,const DebugLoc & dl,unsigned DestReg,unsigned BaseReg,int NumBytes,const TargetInstrInfo & TII,const ARMBaseRegisterInfo & MRI,unsigned MIFlags)178*9880d681SAndroid Build Coastguard Worker void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
179*9880d681SAndroid Build Coastguard Worker                                      MachineBasicBlock::iterator &MBBI,
180*9880d681SAndroid Build Coastguard Worker                                      const DebugLoc &dl, unsigned DestReg,
181*9880d681SAndroid Build Coastguard Worker                                      unsigned BaseReg, int NumBytes,
182*9880d681SAndroid Build Coastguard Worker                                      const TargetInstrInfo &TII,
183*9880d681SAndroid Build Coastguard Worker                                      const ARMBaseRegisterInfo &MRI,
184*9880d681SAndroid Build Coastguard Worker                                      unsigned MIFlags) {
185*9880d681SAndroid Build Coastguard Worker   bool isSub = NumBytes < 0;
186*9880d681SAndroid Build Coastguard Worker   unsigned Bytes = (unsigned)NumBytes;
187*9880d681SAndroid Build Coastguard Worker   if (isSub) Bytes = -NumBytes;
188*9880d681SAndroid Build Coastguard Worker 
189*9880d681SAndroid Build Coastguard Worker   int CopyOpc = 0;
190*9880d681SAndroid Build Coastguard Worker   unsigned CopyBits = 0;
191*9880d681SAndroid Build Coastguard Worker   unsigned CopyScale = 1;
192*9880d681SAndroid Build Coastguard Worker   bool CopyNeedsCC = false;
193*9880d681SAndroid Build Coastguard Worker   int ExtraOpc = 0;
194*9880d681SAndroid Build Coastguard Worker   unsigned ExtraBits = 0;
195*9880d681SAndroid Build Coastguard Worker   unsigned ExtraScale = 1;
196*9880d681SAndroid Build Coastguard Worker   bool ExtraNeedsCC = false;
197*9880d681SAndroid Build Coastguard Worker 
198*9880d681SAndroid Build Coastguard Worker   // Strategy:
199*9880d681SAndroid Build Coastguard Worker   // We need to select two types of instruction, maximizing the available
200*9880d681SAndroid Build Coastguard Worker   // immediate range of each. The instructions we use will depend on whether
201*9880d681SAndroid Build Coastguard Worker   // DestReg and BaseReg are low, high or the stack pointer.
202*9880d681SAndroid Build Coastguard Worker   // * CopyOpc  - DestReg = BaseReg + imm
203*9880d681SAndroid Build Coastguard Worker   //              This will be emitted once if DestReg != BaseReg, and never if
204*9880d681SAndroid Build Coastguard Worker   //              DestReg == BaseReg.
205*9880d681SAndroid Build Coastguard Worker   // * ExtraOpc - DestReg = DestReg + imm
206*9880d681SAndroid Build Coastguard Worker   //              This will be emitted as many times as necessary to add the
207*9880d681SAndroid Build Coastguard Worker   //              full immediate.
208*9880d681SAndroid Build Coastguard Worker   // If the immediate ranges of these instructions are not large enough to cover
209*9880d681SAndroid Build Coastguard Worker   // NumBytes with a reasonable number of instructions, we fall back to using a
210*9880d681SAndroid Build Coastguard Worker   // value loaded from a constant pool.
211*9880d681SAndroid Build Coastguard Worker   if (DestReg == ARM::SP) {
212*9880d681SAndroid Build Coastguard Worker     if (BaseReg == ARM::SP) {
213*9880d681SAndroid Build Coastguard Worker       // sp -> sp
214*9880d681SAndroid Build Coastguard Worker       // Already in right reg, no copy needed
215*9880d681SAndroid Build Coastguard Worker     } else {
216*9880d681SAndroid Build Coastguard Worker       // low -> sp or high -> sp
217*9880d681SAndroid Build Coastguard Worker       CopyOpc = ARM::tMOVr;
218*9880d681SAndroid Build Coastguard Worker       CopyBits = 0;
219*9880d681SAndroid Build Coastguard Worker     }
220*9880d681SAndroid Build Coastguard Worker     ExtraOpc = isSub ? ARM::tSUBspi : ARM::tADDspi;
221*9880d681SAndroid Build Coastguard Worker     ExtraBits = 7;
222*9880d681SAndroid Build Coastguard Worker     ExtraScale = 4;
223*9880d681SAndroid Build Coastguard Worker   } else if (isARMLowRegister(DestReg)) {
224*9880d681SAndroid Build Coastguard Worker     if (BaseReg == ARM::SP) {
225*9880d681SAndroid Build Coastguard Worker       // sp -> low
226*9880d681SAndroid Build Coastguard Worker       assert(!isSub && "Thumb1 does not have tSUBrSPi");
227*9880d681SAndroid Build Coastguard Worker       CopyOpc = ARM::tADDrSPi;
228*9880d681SAndroid Build Coastguard Worker       CopyBits = 8;
229*9880d681SAndroid Build Coastguard Worker       CopyScale = 4;
230*9880d681SAndroid Build Coastguard Worker     } else if (DestReg == BaseReg) {
231*9880d681SAndroid Build Coastguard Worker       // low -> same low
232*9880d681SAndroid Build Coastguard Worker       // Already in right reg, no copy needed
233*9880d681SAndroid Build Coastguard Worker     } else if (isARMLowRegister(BaseReg)) {
234*9880d681SAndroid Build Coastguard Worker       // low -> different low
235*9880d681SAndroid Build Coastguard Worker       CopyOpc = isSub ? ARM::tSUBi3 : ARM::tADDi3;
236*9880d681SAndroid Build Coastguard Worker       CopyBits = 3;
237*9880d681SAndroid Build Coastguard Worker       CopyNeedsCC = true;
238*9880d681SAndroid Build Coastguard Worker     } else {
239*9880d681SAndroid Build Coastguard Worker       // high -> low
240*9880d681SAndroid Build Coastguard Worker       CopyOpc = ARM::tMOVr;
241*9880d681SAndroid Build Coastguard Worker       CopyBits = 0;
242*9880d681SAndroid Build Coastguard Worker     }
243*9880d681SAndroid Build Coastguard Worker     ExtraOpc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
244*9880d681SAndroid Build Coastguard Worker     ExtraBits = 8;
245*9880d681SAndroid Build Coastguard Worker     ExtraNeedsCC = true;
246*9880d681SAndroid Build Coastguard Worker   } else /* DestReg is high */ {
247*9880d681SAndroid Build Coastguard Worker     if (DestReg == BaseReg) {
248*9880d681SAndroid Build Coastguard Worker       // high -> same high
249*9880d681SAndroid Build Coastguard Worker       // Already in right reg, no copy needed
250*9880d681SAndroid Build Coastguard Worker     } else {
251*9880d681SAndroid Build Coastguard Worker       // {low,high,sp} -> high
252*9880d681SAndroid Build Coastguard Worker       CopyOpc = ARM::tMOVr;
253*9880d681SAndroid Build Coastguard Worker       CopyBits = 0;
254*9880d681SAndroid Build Coastguard Worker     }
255*9880d681SAndroid Build Coastguard Worker     ExtraOpc = 0;
256*9880d681SAndroid Build Coastguard Worker   }
257*9880d681SAndroid Build Coastguard Worker 
258*9880d681SAndroid Build Coastguard Worker   // We could handle an unaligned immediate with an unaligned copy instruction
259*9880d681SAndroid Build Coastguard Worker   // and an aligned extra instruction, but this case is not currently needed.
260*9880d681SAndroid Build Coastguard Worker   assert(((Bytes & 3) == 0 || ExtraScale == 1) &&
261*9880d681SAndroid Build Coastguard Worker          "Unaligned offset, but all instructions require alignment");
262*9880d681SAndroid Build Coastguard Worker 
263*9880d681SAndroid Build Coastguard Worker   unsigned CopyRange = ((1 << CopyBits) - 1) * CopyScale;
264*9880d681SAndroid Build Coastguard Worker   // If we would emit the copy with an immediate of 0, just use tMOVr.
265*9880d681SAndroid Build Coastguard Worker   if (CopyOpc && Bytes < CopyScale) {
266*9880d681SAndroid Build Coastguard Worker     CopyOpc = ARM::tMOVr;
267*9880d681SAndroid Build Coastguard Worker     CopyScale = 1;
268*9880d681SAndroid Build Coastguard Worker     CopyNeedsCC = false;
269*9880d681SAndroid Build Coastguard Worker     CopyRange = 0;
270*9880d681SAndroid Build Coastguard Worker   }
271*9880d681SAndroid Build Coastguard Worker   unsigned ExtraRange = ((1 << ExtraBits) - 1) * ExtraScale; // per instruction
272*9880d681SAndroid Build Coastguard Worker   unsigned RequiredCopyInstrs = CopyOpc ? 1 : 0;
273*9880d681SAndroid Build Coastguard Worker   unsigned RangeAfterCopy = (CopyRange > Bytes) ? 0 : (Bytes - CopyRange);
274*9880d681SAndroid Build Coastguard Worker 
275*9880d681SAndroid Build Coastguard Worker   // We could handle this case when the copy instruction does not require an
276*9880d681SAndroid Build Coastguard Worker   // aligned immediate, but we do not currently do this.
277*9880d681SAndroid Build Coastguard Worker   assert(RangeAfterCopy % ExtraScale == 0 &&
278*9880d681SAndroid Build Coastguard Worker          "Extra instruction requires immediate to be aligned");
279*9880d681SAndroid Build Coastguard Worker 
280*9880d681SAndroid Build Coastguard Worker   unsigned RequiredExtraInstrs;
281*9880d681SAndroid Build Coastguard Worker   if (ExtraRange)
282*9880d681SAndroid Build Coastguard Worker     RequiredExtraInstrs = alignTo(RangeAfterCopy, ExtraRange) / ExtraRange;
283*9880d681SAndroid Build Coastguard Worker   else if (RangeAfterCopy > 0)
284*9880d681SAndroid Build Coastguard Worker     // We need an extra instruction but none is available
285*9880d681SAndroid Build Coastguard Worker     RequiredExtraInstrs = 1000000;
286*9880d681SAndroid Build Coastguard Worker   else
287*9880d681SAndroid Build Coastguard Worker     RequiredExtraInstrs = 0;
288*9880d681SAndroid Build Coastguard Worker   unsigned RequiredInstrs = RequiredCopyInstrs + RequiredExtraInstrs;
289*9880d681SAndroid Build Coastguard Worker   unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2;
290*9880d681SAndroid Build Coastguard Worker 
291*9880d681SAndroid Build Coastguard Worker   // Use a constant pool, if the sequence of ADDs/SUBs is too expensive.
292*9880d681SAndroid Build Coastguard Worker   if (RequiredInstrs > Threshold) {
293*9880d681SAndroid Build Coastguard Worker     emitThumbRegPlusImmInReg(MBB, MBBI, dl,
294*9880d681SAndroid Build Coastguard Worker                              DestReg, BaseReg, NumBytes, true,
295*9880d681SAndroid Build Coastguard Worker                              TII, MRI, MIFlags);
296*9880d681SAndroid Build Coastguard Worker     return;
297*9880d681SAndroid Build Coastguard Worker   }
298*9880d681SAndroid Build Coastguard Worker 
299*9880d681SAndroid Build Coastguard Worker   // Emit zero or one copy instructions
300*9880d681SAndroid Build Coastguard Worker   if (CopyOpc) {
301*9880d681SAndroid Build Coastguard Worker     unsigned CopyImm = std::min(Bytes, CopyRange) / CopyScale;
302*9880d681SAndroid Build Coastguard Worker     Bytes -= CopyImm * CopyScale;
303*9880d681SAndroid Build Coastguard Worker 
304*9880d681SAndroid Build Coastguard Worker     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(CopyOpc), DestReg);
305*9880d681SAndroid Build Coastguard Worker     if (CopyNeedsCC)
306*9880d681SAndroid Build Coastguard Worker       MIB = AddDefaultT1CC(MIB);
307*9880d681SAndroid Build Coastguard Worker     MIB.addReg(BaseReg, RegState::Kill);
308*9880d681SAndroid Build Coastguard Worker     if (CopyOpc != ARM::tMOVr) {
309*9880d681SAndroid Build Coastguard Worker       MIB.addImm(CopyImm);
310*9880d681SAndroid Build Coastguard Worker     }
311*9880d681SAndroid Build Coastguard Worker     AddDefaultPred(MIB.setMIFlags(MIFlags));
312*9880d681SAndroid Build Coastguard Worker 
313*9880d681SAndroid Build Coastguard Worker     BaseReg = DestReg;
314*9880d681SAndroid Build Coastguard Worker   }
315*9880d681SAndroid Build Coastguard Worker 
316*9880d681SAndroid Build Coastguard Worker   // Emit zero or more in-place add/sub instructions
317*9880d681SAndroid Build Coastguard Worker   while (Bytes) {
318*9880d681SAndroid Build Coastguard Worker     unsigned ExtraImm = std::min(Bytes, ExtraRange) / ExtraScale;
319*9880d681SAndroid Build Coastguard Worker     Bytes -= ExtraImm * ExtraScale;
320*9880d681SAndroid Build Coastguard Worker 
321*9880d681SAndroid Build Coastguard Worker     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(ExtraOpc), DestReg);
322*9880d681SAndroid Build Coastguard Worker     if (ExtraNeedsCC)
323*9880d681SAndroid Build Coastguard Worker       MIB = AddDefaultT1CC(MIB);
324*9880d681SAndroid Build Coastguard Worker     MIB.addReg(BaseReg).addImm(ExtraImm);
325*9880d681SAndroid Build Coastguard Worker     MIB = AddDefaultPred(MIB);
326*9880d681SAndroid Build Coastguard Worker     MIB.setMIFlags(MIFlags);
327*9880d681SAndroid Build Coastguard Worker   }
328*9880d681SAndroid Build Coastguard Worker }
329*9880d681SAndroid Build Coastguard Worker 
removeOperands(MachineInstr & MI,unsigned i)330*9880d681SAndroid Build Coastguard Worker static void removeOperands(MachineInstr &MI, unsigned i) {
331*9880d681SAndroid Build Coastguard Worker   unsigned Op = i;
332*9880d681SAndroid Build Coastguard Worker   for (unsigned e = MI.getNumOperands(); i != e; ++i)
333*9880d681SAndroid Build Coastguard Worker     MI.RemoveOperand(Op);
334*9880d681SAndroid Build Coastguard Worker }
335*9880d681SAndroid Build Coastguard Worker 
336*9880d681SAndroid Build Coastguard Worker /// convertToNonSPOpcode - Change the opcode to the non-SP version, because
337*9880d681SAndroid Build Coastguard Worker /// we're replacing the frame index with a non-SP register.
convertToNonSPOpcode(unsigned Opcode)338*9880d681SAndroid Build Coastguard Worker static unsigned convertToNonSPOpcode(unsigned Opcode) {
339*9880d681SAndroid Build Coastguard Worker   switch (Opcode) {
340*9880d681SAndroid Build Coastguard Worker   case ARM::tLDRspi:
341*9880d681SAndroid Build Coastguard Worker     return ARM::tLDRi;
342*9880d681SAndroid Build Coastguard Worker 
343*9880d681SAndroid Build Coastguard Worker   case ARM::tSTRspi:
344*9880d681SAndroid Build Coastguard Worker     return ARM::tSTRi;
345*9880d681SAndroid Build Coastguard Worker   }
346*9880d681SAndroid Build Coastguard Worker 
347*9880d681SAndroid Build Coastguard Worker   return Opcode;
348*9880d681SAndroid Build Coastguard Worker }
349*9880d681SAndroid Build Coastguard Worker 
rewriteFrameIndex(MachineBasicBlock::iterator II,unsigned FrameRegIdx,unsigned FrameReg,int & Offset,const ARMBaseInstrInfo & TII) const350*9880d681SAndroid Build Coastguard Worker bool ThumbRegisterInfo::rewriteFrameIndex(MachineBasicBlock::iterator II,
351*9880d681SAndroid Build Coastguard Worker                                           unsigned FrameRegIdx,
352*9880d681SAndroid Build Coastguard Worker                                           unsigned FrameReg, int &Offset,
353*9880d681SAndroid Build Coastguard Worker                                           const ARMBaseInstrInfo &TII) const {
354*9880d681SAndroid Build Coastguard Worker   MachineInstr &MI = *II;
355*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock &MBB = *MI.getParent();
356*9880d681SAndroid Build Coastguard Worker   assert(MBB.getParent()->getSubtarget<ARMSubtarget>().isThumb1Only() &&
357*9880d681SAndroid Build Coastguard Worker          "This isn't needed for thumb2!");
358*9880d681SAndroid Build Coastguard Worker   DebugLoc dl = MI.getDebugLoc();
359*9880d681SAndroid Build Coastguard Worker   MachineInstrBuilder MIB(*MBB.getParent(), &MI);
360*9880d681SAndroid Build Coastguard Worker   unsigned Opcode = MI.getOpcode();
361*9880d681SAndroid Build Coastguard Worker   const MCInstrDesc &Desc = MI.getDesc();
362*9880d681SAndroid Build Coastguard Worker   unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
363*9880d681SAndroid Build Coastguard Worker 
364*9880d681SAndroid Build Coastguard Worker   if (Opcode == ARM::tADDframe) {
365*9880d681SAndroid Build Coastguard Worker     Offset += MI.getOperand(FrameRegIdx+1).getImm();
366*9880d681SAndroid Build Coastguard Worker     unsigned DestReg = MI.getOperand(0).getReg();
367*9880d681SAndroid Build Coastguard Worker 
368*9880d681SAndroid Build Coastguard Worker     emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII,
369*9880d681SAndroid Build Coastguard Worker                               *this);
370*9880d681SAndroid Build Coastguard Worker     MBB.erase(II);
371*9880d681SAndroid Build Coastguard Worker     return true;
372*9880d681SAndroid Build Coastguard Worker   } else {
373*9880d681SAndroid Build Coastguard Worker     if (AddrMode != ARMII::AddrModeT1_s)
374*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Unsupported addressing mode!");
375*9880d681SAndroid Build Coastguard Worker 
376*9880d681SAndroid Build Coastguard Worker     unsigned ImmIdx = FrameRegIdx + 1;
377*9880d681SAndroid Build Coastguard Worker     int InstrOffs = MI.getOperand(ImmIdx).getImm();
378*9880d681SAndroid Build Coastguard Worker     unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5;
379*9880d681SAndroid Build Coastguard Worker     unsigned Scale = 4;
380*9880d681SAndroid Build Coastguard Worker 
381*9880d681SAndroid Build Coastguard Worker     Offset += InstrOffs * Scale;
382*9880d681SAndroid Build Coastguard Worker     assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!");
383*9880d681SAndroid Build Coastguard Worker 
384*9880d681SAndroid Build Coastguard Worker     // Common case: small offset, fits into instruction.
385*9880d681SAndroid Build Coastguard Worker     MachineOperand &ImmOp = MI.getOperand(ImmIdx);
386*9880d681SAndroid Build Coastguard Worker     int ImmedOffset = Offset / Scale;
387*9880d681SAndroid Build Coastguard Worker     unsigned Mask = (1 << NumBits) - 1;
388*9880d681SAndroid Build Coastguard Worker 
389*9880d681SAndroid Build Coastguard Worker     if ((unsigned)Offset <= Mask * Scale) {
390*9880d681SAndroid Build Coastguard Worker       // Replace the FrameIndex with the frame register (e.g., sp).
391*9880d681SAndroid Build Coastguard Worker       MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
392*9880d681SAndroid Build Coastguard Worker       ImmOp.ChangeToImmediate(ImmedOffset);
393*9880d681SAndroid Build Coastguard Worker 
394*9880d681SAndroid Build Coastguard Worker       // If we're using a register where sp was stored, convert the instruction
395*9880d681SAndroid Build Coastguard Worker       // to the non-SP version.
396*9880d681SAndroid Build Coastguard Worker       unsigned NewOpc = convertToNonSPOpcode(Opcode);
397*9880d681SAndroid Build Coastguard Worker       if (NewOpc != Opcode && FrameReg != ARM::SP)
398*9880d681SAndroid Build Coastguard Worker         MI.setDesc(TII.get(NewOpc));
399*9880d681SAndroid Build Coastguard Worker 
400*9880d681SAndroid Build Coastguard Worker       return true;
401*9880d681SAndroid Build Coastguard Worker     }
402*9880d681SAndroid Build Coastguard Worker 
403*9880d681SAndroid Build Coastguard Worker     NumBits = 5;
404*9880d681SAndroid Build Coastguard Worker     Mask = (1 << NumBits) - 1;
405*9880d681SAndroid Build Coastguard Worker 
406*9880d681SAndroid Build Coastguard Worker     // If this is a thumb spill / restore, we will be using a constpool load to
407*9880d681SAndroid Build Coastguard Worker     // materialize the offset.
408*9880d681SAndroid Build Coastguard Worker     if (Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {
409*9880d681SAndroid Build Coastguard Worker       ImmOp.ChangeToImmediate(0);
410*9880d681SAndroid Build Coastguard Worker     } else {
411*9880d681SAndroid Build Coastguard Worker       // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
412*9880d681SAndroid Build Coastguard Worker       ImmedOffset = ImmedOffset & Mask;
413*9880d681SAndroid Build Coastguard Worker       ImmOp.ChangeToImmediate(ImmedOffset);
414*9880d681SAndroid Build Coastguard Worker       Offset &= ~(Mask * Scale);
415*9880d681SAndroid Build Coastguard Worker     }
416*9880d681SAndroid Build Coastguard Worker   }
417*9880d681SAndroid Build Coastguard Worker 
418*9880d681SAndroid Build Coastguard Worker   return Offset == 0;
419*9880d681SAndroid Build Coastguard Worker }
420*9880d681SAndroid Build Coastguard Worker 
resolveFrameIndex(MachineInstr & MI,unsigned BaseReg,int64_t Offset) const421*9880d681SAndroid Build Coastguard Worker void ThumbRegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg,
422*9880d681SAndroid Build Coastguard Worker                                            int64_t Offset) const {
423*9880d681SAndroid Build Coastguard Worker   const MachineFunction &MF = *MI.getParent()->getParent();
424*9880d681SAndroid Build Coastguard Worker   const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
425*9880d681SAndroid Build Coastguard Worker   if (!STI.isThumb1Only())
426*9880d681SAndroid Build Coastguard Worker     return ARMBaseRegisterInfo::resolveFrameIndex(MI, BaseReg, Offset);
427*9880d681SAndroid Build Coastguard Worker 
428*9880d681SAndroid Build Coastguard Worker   const ARMBaseInstrInfo &TII = *STI.getInstrInfo();
429*9880d681SAndroid Build Coastguard Worker   int Off = Offset; // ARM doesn't need the general 64-bit offsets
430*9880d681SAndroid Build Coastguard Worker   unsigned i = 0;
431*9880d681SAndroid Build Coastguard Worker 
432*9880d681SAndroid Build Coastguard Worker   while (!MI.getOperand(i).isFI()) {
433*9880d681SAndroid Build Coastguard Worker     ++i;
434*9880d681SAndroid Build Coastguard Worker     assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
435*9880d681SAndroid Build Coastguard Worker   }
436*9880d681SAndroid Build Coastguard Worker   bool Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII);
437*9880d681SAndroid Build Coastguard Worker   assert (Done && "Unable to resolve frame index!");
438*9880d681SAndroid Build Coastguard Worker   (void)Done;
439*9880d681SAndroid Build Coastguard Worker }
440*9880d681SAndroid Build Coastguard Worker 
441*9880d681SAndroid Build Coastguard Worker /// saveScavengerRegister - Spill the register so it can be used by the
442*9880d681SAndroid Build Coastguard Worker /// register scavenger. Return true.
saveScavengerRegister(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,MachineBasicBlock::iterator & UseMI,const TargetRegisterClass * RC,unsigned Reg) const443*9880d681SAndroid Build Coastguard Worker bool ThumbRegisterInfo::saveScavengerRegister(
444*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
445*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::iterator &UseMI, const TargetRegisterClass *RC,
446*9880d681SAndroid Build Coastguard Worker     unsigned Reg) const {
447*9880d681SAndroid Build Coastguard Worker 
448*9880d681SAndroid Build Coastguard Worker   const ARMSubtarget &STI = MBB.getParent()->getSubtarget<ARMSubtarget>();
449*9880d681SAndroid Build Coastguard Worker   if (!STI.isThumb1Only())
450*9880d681SAndroid Build Coastguard Worker     return ARMBaseRegisterInfo::saveScavengerRegister(MBB, I, UseMI, RC, Reg);
451*9880d681SAndroid Build Coastguard Worker 
452*9880d681SAndroid Build Coastguard Worker   // Thumb1 can't use the emergency spill slot on the stack because
453*9880d681SAndroid Build Coastguard Worker   // ldr/str immediate offsets must be positive, and if we're referencing
454*9880d681SAndroid Build Coastguard Worker   // off the frame pointer (if, for example, there are alloca() calls in
455*9880d681SAndroid Build Coastguard Worker   // the function, the offset will be negative. Use R12 instead since that's
456*9880d681SAndroid Build Coastguard Worker   // a call clobbered register that we know won't be used in Thumb1 mode.
457*9880d681SAndroid Build Coastguard Worker   const TargetInstrInfo &TII = *STI.getInstrInfo();
458*9880d681SAndroid Build Coastguard Worker   DebugLoc DL;
459*9880d681SAndroid Build Coastguard Worker   AddDefaultPred(BuildMI(MBB, I, DL, TII.get(ARM::tMOVr))
460*9880d681SAndroid Build Coastguard Worker     .addReg(ARM::R12, RegState::Define)
461*9880d681SAndroid Build Coastguard Worker     .addReg(Reg, RegState::Kill));
462*9880d681SAndroid Build Coastguard Worker 
463*9880d681SAndroid Build Coastguard Worker   // The UseMI is where we would like to restore the register. If there's
464*9880d681SAndroid Build Coastguard Worker   // interference with R12 before then, however, we'll need to restore it
465*9880d681SAndroid Build Coastguard Worker   // before that instead and adjust the UseMI.
466*9880d681SAndroid Build Coastguard Worker   bool done = false;
467*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) {
468*9880d681SAndroid Build Coastguard Worker     if (II->isDebugValue())
469*9880d681SAndroid Build Coastguard Worker       continue;
470*9880d681SAndroid Build Coastguard Worker     // If this instruction affects R12, adjust our restore point.
471*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) {
472*9880d681SAndroid Build Coastguard Worker       const MachineOperand &MO = II->getOperand(i);
473*9880d681SAndroid Build Coastguard Worker       if (MO.isRegMask() && MO.clobbersPhysReg(ARM::R12)) {
474*9880d681SAndroid Build Coastguard Worker         UseMI = II;
475*9880d681SAndroid Build Coastguard Worker         done = true;
476*9880d681SAndroid Build Coastguard Worker         break;
477*9880d681SAndroid Build Coastguard Worker       }
478*9880d681SAndroid Build Coastguard Worker       if (!MO.isReg() || MO.isUndef() || !MO.getReg() ||
479*9880d681SAndroid Build Coastguard Worker           TargetRegisterInfo::isVirtualRegister(MO.getReg()))
480*9880d681SAndroid Build Coastguard Worker         continue;
481*9880d681SAndroid Build Coastguard Worker       if (MO.getReg() == ARM::R12) {
482*9880d681SAndroid Build Coastguard Worker         UseMI = II;
483*9880d681SAndroid Build Coastguard Worker         done = true;
484*9880d681SAndroid Build Coastguard Worker         break;
485*9880d681SAndroid Build Coastguard Worker       }
486*9880d681SAndroid Build Coastguard Worker     }
487*9880d681SAndroid Build Coastguard Worker   }
488*9880d681SAndroid Build Coastguard Worker   // Restore the register from R12
489*9880d681SAndroid Build Coastguard Worker   AddDefaultPred(BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVr)).
490*9880d681SAndroid Build Coastguard Worker     addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill));
491*9880d681SAndroid Build Coastguard Worker 
492*9880d681SAndroid Build Coastguard Worker   return true;
493*9880d681SAndroid Build Coastguard Worker }
494*9880d681SAndroid Build Coastguard Worker 
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const495*9880d681SAndroid Build Coastguard Worker void ThumbRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
496*9880d681SAndroid Build Coastguard Worker                                             int SPAdj, unsigned FIOperandNum,
497*9880d681SAndroid Build Coastguard Worker                                             RegScavenger *RS) const {
498*9880d681SAndroid Build Coastguard Worker   MachineInstr &MI = *II;
499*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock &MBB = *MI.getParent();
500*9880d681SAndroid Build Coastguard Worker   MachineFunction &MF = *MBB.getParent();
501*9880d681SAndroid Build Coastguard Worker   const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
502*9880d681SAndroid Build Coastguard Worker   if (!STI.isThumb1Only())
503*9880d681SAndroid Build Coastguard Worker     return ARMBaseRegisterInfo::eliminateFrameIndex(II, SPAdj, FIOperandNum,
504*9880d681SAndroid Build Coastguard Worker                                                     RS);
505*9880d681SAndroid Build Coastguard Worker 
506*9880d681SAndroid Build Coastguard Worker   unsigned VReg = 0;
507*9880d681SAndroid Build Coastguard Worker   const ARMBaseInstrInfo &TII = *STI.getInstrInfo();
508*9880d681SAndroid Build Coastguard Worker   ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
509*9880d681SAndroid Build Coastguard Worker   DebugLoc dl = MI.getDebugLoc();
510*9880d681SAndroid Build Coastguard Worker   MachineInstrBuilder MIB(*MBB.getParent(), &MI);
511*9880d681SAndroid Build Coastguard Worker 
512*9880d681SAndroid Build Coastguard Worker   unsigned FrameReg = ARM::SP;
513*9880d681SAndroid Build Coastguard Worker   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
514*9880d681SAndroid Build Coastguard Worker   int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
515*9880d681SAndroid Build Coastguard Worker                MF.getFrameInfo()->getStackSize() + SPAdj;
516*9880d681SAndroid Build Coastguard Worker 
517*9880d681SAndroid Build Coastguard Worker   if (MF.getFrameInfo()->hasVarSizedObjects()) {
518*9880d681SAndroid Build Coastguard Worker     assert(SPAdj == 0 && STI.getFrameLowering()->hasFP(MF) && "Unexpected");
519*9880d681SAndroid Build Coastguard Worker     // There are alloca()'s in this function, must reference off the frame
520*9880d681SAndroid Build Coastguard Worker     // pointer or base pointer instead.
521*9880d681SAndroid Build Coastguard Worker     if (!hasBasePointer(MF)) {
522*9880d681SAndroid Build Coastguard Worker       FrameReg = getFrameRegister(MF);
523*9880d681SAndroid Build Coastguard Worker       Offset -= AFI->getFramePtrSpillOffset();
524*9880d681SAndroid Build Coastguard Worker     } else
525*9880d681SAndroid Build Coastguard Worker       FrameReg = BasePtr;
526*9880d681SAndroid Build Coastguard Worker   }
527*9880d681SAndroid Build Coastguard Worker 
528*9880d681SAndroid Build Coastguard Worker   // PEI::scavengeFrameVirtualRegs() cannot accurately track SPAdj because the
529*9880d681SAndroid Build Coastguard Worker   // call frame setup/destroy instructions have already been eliminated.  That
530*9880d681SAndroid Build Coastguard Worker   // means the stack pointer cannot be used to access the emergency spill slot
531*9880d681SAndroid Build Coastguard Worker   // when !hasReservedCallFrame().
532*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
533*9880d681SAndroid Build Coastguard Worker   if (RS && FrameReg == ARM::SP && RS->isScavengingFrameIndex(FrameIndex)){
534*9880d681SAndroid Build Coastguard Worker     assert(STI.getFrameLowering()->hasReservedCallFrame(MF) &&
535*9880d681SAndroid Build Coastguard Worker            "Cannot use SP to access the emergency spill slot in "
536*9880d681SAndroid Build Coastguard Worker            "functions without a reserved call frame");
537*9880d681SAndroid Build Coastguard Worker     assert(!MF.getFrameInfo()->hasVarSizedObjects() &&
538*9880d681SAndroid Build Coastguard Worker            "Cannot use SP to access the emergency spill slot in "
539*9880d681SAndroid Build Coastguard Worker            "functions with variable sized frame objects");
540*9880d681SAndroid Build Coastguard Worker   }
541*9880d681SAndroid Build Coastguard Worker #endif // NDEBUG
542*9880d681SAndroid Build Coastguard Worker 
543*9880d681SAndroid Build Coastguard Worker   // Special handling of dbg_value instructions.
544*9880d681SAndroid Build Coastguard Worker   if (MI.isDebugValue()) {
545*9880d681SAndroid Build Coastguard Worker     MI.getOperand(FIOperandNum).  ChangeToRegister(FrameReg, false /*isDef*/);
546*9880d681SAndroid Build Coastguard Worker     MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
547*9880d681SAndroid Build Coastguard Worker     return;
548*9880d681SAndroid Build Coastguard Worker   }
549*9880d681SAndroid Build Coastguard Worker 
550*9880d681SAndroid Build Coastguard Worker   // Modify MI as necessary to handle as much of 'Offset' as possible
551*9880d681SAndroid Build Coastguard Worker   assert(AFI->isThumbFunction() &&
552*9880d681SAndroid Build Coastguard Worker          "This eliminateFrameIndex only supports Thumb1!");
553*9880d681SAndroid Build Coastguard Worker   if (rewriteFrameIndex(MI, FIOperandNum, FrameReg, Offset, TII))
554*9880d681SAndroid Build Coastguard Worker     return;
555*9880d681SAndroid Build Coastguard Worker 
556*9880d681SAndroid Build Coastguard Worker   // If we get here, the immediate doesn't fit into the instruction.  We folded
557*9880d681SAndroid Build Coastguard Worker   // as much as possible above, handle the rest, providing a register that is
558*9880d681SAndroid Build Coastguard Worker   // SP+LargeImm.
559*9880d681SAndroid Build Coastguard Worker   assert(Offset && "This code isn't needed if offset already handled!");
560*9880d681SAndroid Build Coastguard Worker 
561*9880d681SAndroid Build Coastguard Worker   unsigned Opcode = MI.getOpcode();
562*9880d681SAndroid Build Coastguard Worker 
563*9880d681SAndroid Build Coastguard Worker   // Remove predicate first.
564*9880d681SAndroid Build Coastguard Worker   int PIdx = MI.findFirstPredOperandIdx();
565*9880d681SAndroid Build Coastguard Worker   if (PIdx != -1)
566*9880d681SAndroid Build Coastguard Worker     removeOperands(MI, PIdx);
567*9880d681SAndroid Build Coastguard Worker 
568*9880d681SAndroid Build Coastguard Worker   if (MI.mayLoad()) {
569*9880d681SAndroid Build Coastguard Worker     // Use the destination register to materialize sp + offset.
570*9880d681SAndroid Build Coastguard Worker     unsigned TmpReg = MI.getOperand(0).getReg();
571*9880d681SAndroid Build Coastguard Worker     bool UseRR = false;
572*9880d681SAndroid Build Coastguard Worker     if (Opcode == ARM::tLDRspi) {
573*9880d681SAndroid Build Coastguard Worker       if (FrameReg == ARM::SP)
574*9880d681SAndroid Build Coastguard Worker         emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg,
575*9880d681SAndroid Build Coastguard Worker                                  Offset, false, TII, *this);
576*9880d681SAndroid Build Coastguard Worker       else {
577*9880d681SAndroid Build Coastguard Worker         emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset);
578*9880d681SAndroid Build Coastguard Worker         UseRR = true;
579*9880d681SAndroid Build Coastguard Worker       }
580*9880d681SAndroid Build Coastguard Worker     } else {
581*9880d681SAndroid Build Coastguard Worker       emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII,
582*9880d681SAndroid Build Coastguard Worker                                 *this);
583*9880d681SAndroid Build Coastguard Worker     }
584*9880d681SAndroid Build Coastguard Worker 
585*9880d681SAndroid Build Coastguard Worker     MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi));
586*9880d681SAndroid Build Coastguard Worker     MI.getOperand(FIOperandNum).ChangeToRegister(TmpReg, false, false, true);
587*9880d681SAndroid Build Coastguard Worker     if (UseRR)
588*9880d681SAndroid Build Coastguard Worker       // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
589*9880d681SAndroid Build Coastguard Worker       // register. The offset is already handled in the vreg value.
590*9880d681SAndroid Build Coastguard Worker       MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false,
591*9880d681SAndroid Build Coastguard Worker                                                      false);
592*9880d681SAndroid Build Coastguard Worker   } else if (MI.mayStore()) {
593*9880d681SAndroid Build Coastguard Worker       VReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);
594*9880d681SAndroid Build Coastguard Worker       bool UseRR = false;
595*9880d681SAndroid Build Coastguard Worker 
596*9880d681SAndroid Build Coastguard Worker       if (Opcode == ARM::tSTRspi) {
597*9880d681SAndroid Build Coastguard Worker         if (FrameReg == ARM::SP)
598*9880d681SAndroid Build Coastguard Worker           emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg,
599*9880d681SAndroid Build Coastguard Worker                                    Offset, false, TII, *this);
600*9880d681SAndroid Build Coastguard Worker         else {
601*9880d681SAndroid Build Coastguard Worker           emitLoadConstPool(MBB, II, dl, VReg, 0, Offset);
602*9880d681SAndroid Build Coastguard Worker           UseRR = true;
603*9880d681SAndroid Build Coastguard Worker         }
604*9880d681SAndroid Build Coastguard Worker       } else
605*9880d681SAndroid Build Coastguard Worker         emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII,
606*9880d681SAndroid Build Coastguard Worker                                   *this);
607*9880d681SAndroid Build Coastguard Worker       MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi));
608*9880d681SAndroid Build Coastguard Worker       MI.getOperand(FIOperandNum).ChangeToRegister(VReg, false, false, true);
609*9880d681SAndroid Build Coastguard Worker       if (UseRR)
610*9880d681SAndroid Build Coastguard Worker         // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
611*9880d681SAndroid Build Coastguard Worker         // register. The offset is already handled in the vreg value.
612*9880d681SAndroid Build Coastguard Worker         MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false,
613*9880d681SAndroid Build Coastguard Worker                                                        false);
614*9880d681SAndroid Build Coastguard Worker   } else {
615*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Unexpected opcode!");
616*9880d681SAndroid Build Coastguard Worker   }
617*9880d681SAndroid Build Coastguard Worker 
618*9880d681SAndroid Build Coastguard Worker   // Add predicate back if it's needed.
619*9880d681SAndroid Build Coastguard Worker   if (MI.isPredicable())
620*9880d681SAndroid Build Coastguard Worker     AddDefaultPred(MIB);
621*9880d681SAndroid Build Coastguard Worker }
622