xref: /openbsd-src/gnu/llvm/llvm/lib/Target/ARM/ThumbRegisterInfo.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- ThumbRegisterInfo.cpp - Thumb-1 Register Information -------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file contains the Thumb-1 implementation of the TargetRegisterInfo
1009467b48Spatrick // class.
1109467b48Spatrick //
1209467b48Spatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick 
1409467b48Spatrick #include "ThumbRegisterInfo.h"
1509467b48Spatrick #include "ARMBaseInstrInfo.h"
1609467b48Spatrick #include "ARMMachineFunctionInfo.h"
1709467b48Spatrick #include "ARMSubtarget.h"
1809467b48Spatrick #include "MCTargetDesc/ARMAddressingModes.h"
1909467b48Spatrick #include "llvm/CodeGen/MachineConstantPool.h"
2009467b48Spatrick #include "llvm/CodeGen/MachineFrameInfo.h"
2109467b48Spatrick #include "llvm/CodeGen/MachineFunction.h"
2209467b48Spatrick #include "llvm/CodeGen/MachineInstrBuilder.h"
2309467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
2409467b48Spatrick #include "llvm/CodeGen/RegisterScavenging.h"
2509467b48Spatrick #include "llvm/IR/Constants.h"
2609467b48Spatrick #include "llvm/IR/DerivedTypes.h"
2709467b48Spatrick #include "llvm/IR/Function.h"
2809467b48Spatrick #include "llvm/IR/LLVMContext.h"
2909467b48Spatrick #include "llvm/Support/CommandLine.h"
3009467b48Spatrick #include "llvm/Support/ErrorHandling.h"
3109467b48Spatrick #include "llvm/CodeGen/TargetFrameLowering.h"
3209467b48Spatrick #include "llvm/Target/TargetMachine.h"
3309467b48Spatrick 
3409467b48Spatrick namespace llvm {
3509467b48Spatrick extern cl::opt<bool> ReuseFrameIndexVals;
3609467b48Spatrick }
3709467b48Spatrick 
3809467b48Spatrick using namespace llvm;
3909467b48Spatrick 
40*d415bd75Srobert ThumbRegisterInfo::ThumbRegisterInfo() = default;
4109467b48Spatrick 
4209467b48Spatrick const TargetRegisterClass *
getLargestLegalSuperClass(const TargetRegisterClass * RC,const MachineFunction & MF) const4309467b48Spatrick ThumbRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
4409467b48Spatrick                                               const MachineFunction &MF) const {
4509467b48Spatrick   if (!MF.getSubtarget<ARMSubtarget>().isThumb1Only())
4609467b48Spatrick     return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC, MF);
4709467b48Spatrick 
4809467b48Spatrick   if (ARM::tGPRRegClass.hasSubClassEq(RC))
4909467b48Spatrick     return &ARM::tGPRRegClass;
5009467b48Spatrick   return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC, MF);
5109467b48Spatrick }
5209467b48Spatrick 
5309467b48Spatrick const TargetRegisterClass *
getPointerRegClass(const MachineFunction & MF,unsigned Kind) const5409467b48Spatrick ThumbRegisterInfo::getPointerRegClass(const MachineFunction &MF,
5509467b48Spatrick                                       unsigned Kind) const {
5609467b48Spatrick   if (!MF.getSubtarget<ARMSubtarget>().isThumb1Only())
5709467b48Spatrick     return ARMBaseRegisterInfo::getPointerRegClass(MF, Kind);
5809467b48Spatrick   return &ARM::tGPRRegClass;
5909467b48Spatrick }
6009467b48Spatrick 
emitThumb1LoadConstPool(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI,const DebugLoc & dl,unsigned DestReg,unsigned SubIdx,int Val,ARMCC::CondCodes Pred,unsigned PredReg,unsigned MIFlags)6109467b48Spatrick static void emitThumb1LoadConstPool(MachineBasicBlock &MBB,
6209467b48Spatrick                                     MachineBasicBlock::iterator &MBBI,
6309467b48Spatrick                                     const DebugLoc &dl, unsigned DestReg,
6409467b48Spatrick                                     unsigned SubIdx, int Val,
6509467b48Spatrick                                     ARMCC::CondCodes Pred, unsigned PredReg,
6609467b48Spatrick                                     unsigned MIFlags) {
6709467b48Spatrick   MachineFunction &MF = *MBB.getParent();
6809467b48Spatrick   const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
6909467b48Spatrick   const TargetInstrInfo &TII = *STI.getInstrInfo();
7009467b48Spatrick   MachineConstantPool *ConstantPool = MF.getConstantPool();
7109467b48Spatrick   const Constant *C = ConstantInt::get(
7209467b48Spatrick           Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), Val);
73097a140dSpatrick   unsigned Idx = ConstantPool->getConstantPoolIndex(C, Align(4));
7409467b48Spatrick 
7509467b48Spatrick   BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRpci))
7609467b48Spatrick     .addReg(DestReg, getDefRegState(true), SubIdx)
7709467b48Spatrick     .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg)
7809467b48Spatrick     .setMIFlags(MIFlags);
7909467b48Spatrick }
8009467b48Spatrick 
emitThumb2LoadConstPool(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI,const DebugLoc & dl,unsigned DestReg,unsigned SubIdx,int Val,ARMCC::CondCodes Pred,unsigned PredReg,unsigned MIFlags)8109467b48Spatrick static void emitThumb2LoadConstPool(MachineBasicBlock &MBB,
8209467b48Spatrick                                     MachineBasicBlock::iterator &MBBI,
8309467b48Spatrick                                     const DebugLoc &dl, unsigned DestReg,
8409467b48Spatrick                                     unsigned SubIdx, int Val,
8509467b48Spatrick                                     ARMCC::CondCodes Pred, unsigned PredReg,
8609467b48Spatrick                                     unsigned MIFlags) {
8709467b48Spatrick   MachineFunction &MF = *MBB.getParent();
8809467b48Spatrick   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
8909467b48Spatrick   MachineConstantPool *ConstantPool = MF.getConstantPool();
9009467b48Spatrick   const Constant *C = ConstantInt::get(
9109467b48Spatrick            Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), Val);
92097a140dSpatrick   unsigned Idx = ConstantPool->getConstantPoolIndex(C, Align(4));
9309467b48Spatrick 
9409467b48Spatrick   BuildMI(MBB, MBBI, dl, TII.get(ARM::t2LDRpci))
9509467b48Spatrick       .addReg(DestReg, getDefRegState(true), SubIdx)
9609467b48Spatrick       .addConstantPoolIndex(Idx)
9709467b48Spatrick       .add(predOps(ARMCC::AL))
9809467b48Spatrick       .setMIFlags(MIFlags);
9909467b48Spatrick }
10009467b48Spatrick 
10109467b48Spatrick /// emitLoadConstPool - Emits a load from constpool to materialize the
10209467b48Spatrick /// specified immediate.
emitLoadConstPool(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI,const DebugLoc & dl,Register DestReg,unsigned SubIdx,int Val,ARMCC::CondCodes Pred,Register PredReg,unsigned MIFlags) const10309467b48Spatrick void ThumbRegisterInfo::emitLoadConstPool(
10409467b48Spatrick     MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
105097a140dSpatrick     const DebugLoc &dl, Register DestReg, unsigned SubIdx, int Val,
106097a140dSpatrick     ARMCC::CondCodes Pred, Register PredReg, unsigned MIFlags) const {
10709467b48Spatrick   MachineFunction &MF = *MBB.getParent();
10809467b48Spatrick   const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
10909467b48Spatrick   if (STI.isThumb1Only()) {
110097a140dSpatrick     assert((isARMLowRegister(DestReg) || DestReg.isVirtual()) &&
11109467b48Spatrick            "Thumb1 does not have ldr to high register");
11209467b48Spatrick     return emitThumb1LoadConstPool(MBB, MBBI, dl, DestReg, SubIdx, Val, Pred,
11309467b48Spatrick                                    PredReg, MIFlags);
11409467b48Spatrick   }
11509467b48Spatrick   return emitThumb2LoadConstPool(MBB, MBBI, dl, DestReg, SubIdx, Val, Pred,
11609467b48Spatrick                                  PredReg, MIFlags);
11709467b48Spatrick }
11809467b48Spatrick 
11909467b48Spatrick /// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize
12009467b48Spatrick /// a destreg = basereg + immediate in Thumb code. Materialize the immediate
12109467b48Spatrick /// in a register using mov / mvn sequences or load the immediate from a
12209467b48Spatrick /// constpool entry.
emitThumbRegPlusImmInReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI,const DebugLoc & dl,Register DestReg,Register BaseReg,int NumBytes,bool CanChangeCC,const TargetInstrInfo & TII,const ARMBaseRegisterInfo & MRI,unsigned MIFlags=MachineInstr::NoFlags)12309467b48Spatrick static void emitThumbRegPlusImmInReg(
12409467b48Spatrick     MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
125097a140dSpatrick     const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes,
12609467b48Spatrick     bool CanChangeCC, const TargetInstrInfo &TII,
12709467b48Spatrick     const ARMBaseRegisterInfo &MRI, unsigned MIFlags = MachineInstr::NoFlags) {
12809467b48Spatrick   MachineFunction &MF = *MBB.getParent();
12909467b48Spatrick   const ARMSubtarget &ST = MF.getSubtarget<ARMSubtarget>();
13009467b48Spatrick   bool isHigh = !isARMLowRegister(DestReg) ||
13109467b48Spatrick                 (BaseReg != 0 && !isARMLowRegister(BaseReg));
13209467b48Spatrick   bool isSub = false;
13309467b48Spatrick   // Subtract doesn't have high register version. Load the negative value
13409467b48Spatrick   // if either base or dest register is a high register. Also, if do not
13509467b48Spatrick   // issue sub as part of the sequence if condition register is to be
13609467b48Spatrick   // preserved.
13709467b48Spatrick   if (NumBytes < 0 && !isHigh && CanChangeCC) {
13809467b48Spatrick     isSub = true;
13909467b48Spatrick     NumBytes = -NumBytes;
14009467b48Spatrick   }
141097a140dSpatrick   Register LdReg = DestReg;
14209467b48Spatrick   if (DestReg == ARM::SP)
14309467b48Spatrick     assert(BaseReg == ARM::SP && "Unexpected!");
144*d415bd75Srobert   if (!isARMLowRegister(DestReg) && !DestReg.isVirtual())
14509467b48Spatrick     LdReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);
14609467b48Spatrick 
14709467b48Spatrick   if (NumBytes <= 255 && NumBytes >= 0 && CanChangeCC) {
14809467b48Spatrick     BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)
14909467b48Spatrick         .add(t1CondCodeOp())
15009467b48Spatrick         .addImm(NumBytes)
15109467b48Spatrick         .setMIFlags(MIFlags);
15209467b48Spatrick   } else if (NumBytes < 0 && NumBytes >= -255 && CanChangeCC) {
15309467b48Spatrick     BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)
15409467b48Spatrick         .add(t1CondCodeOp())
15509467b48Spatrick         .addImm(NumBytes)
15609467b48Spatrick         .setMIFlags(MIFlags);
15709467b48Spatrick     BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg)
15809467b48Spatrick         .add(t1CondCodeOp())
15909467b48Spatrick         .addReg(LdReg, RegState::Kill)
16009467b48Spatrick         .setMIFlags(MIFlags);
16109467b48Spatrick   } else if (ST.genExecuteOnly()) {
16209467b48Spatrick     BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), LdReg)
16309467b48Spatrick       .addImm(NumBytes).setMIFlags(MIFlags);
16409467b48Spatrick   } else
16509467b48Spatrick     MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes, ARMCC::AL, 0,
16609467b48Spatrick                           MIFlags);
16709467b48Spatrick 
16809467b48Spatrick   // Emit add / sub.
16909467b48Spatrick   int Opc = (isSub) ? ARM::tSUBrr
17009467b48Spatrick                     : ((isHigh || !CanChangeCC) ? ARM::tADDhirr : ARM::tADDrr);
17109467b48Spatrick   MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
17209467b48Spatrick   if (Opc != ARM::tADDhirr)
17309467b48Spatrick     MIB = MIB.add(t1CondCodeOp());
17409467b48Spatrick   if (DestReg == ARM::SP || isSub)
17509467b48Spatrick     MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill);
17609467b48Spatrick   else
17709467b48Spatrick     MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill);
17809467b48Spatrick   MIB.add(predOps(ARMCC::AL));
17909467b48Spatrick }
18009467b48Spatrick 
18109467b48Spatrick /// emitThumbRegPlusImmediate - Emits a series of instructions to materialize
18209467b48Spatrick /// a destreg = basereg + immediate in Thumb code. Tries a series of ADDs or
18309467b48Spatrick /// SUBs first, and uses a constant pool value if the instruction sequence would
18409467b48Spatrick /// be too long. This is allowed to modify the condition flags.
emitThumbRegPlusImmediate(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI,const DebugLoc & dl,Register DestReg,Register BaseReg,int NumBytes,const TargetInstrInfo & TII,const ARMBaseRegisterInfo & MRI,unsigned MIFlags)18509467b48Spatrick void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
18609467b48Spatrick                                      MachineBasicBlock::iterator &MBBI,
187097a140dSpatrick                                      const DebugLoc &dl, Register DestReg,
188097a140dSpatrick                                      Register BaseReg, int NumBytes,
18909467b48Spatrick                                      const TargetInstrInfo &TII,
19009467b48Spatrick                                      const ARMBaseRegisterInfo &MRI,
19109467b48Spatrick                                      unsigned MIFlags) {
19209467b48Spatrick   bool isSub = NumBytes < 0;
19309467b48Spatrick   unsigned Bytes = (unsigned)NumBytes;
19409467b48Spatrick   if (isSub) Bytes = -NumBytes;
19509467b48Spatrick 
19609467b48Spatrick   int CopyOpc = 0;
19709467b48Spatrick   unsigned CopyBits = 0;
19809467b48Spatrick   unsigned CopyScale = 1;
19909467b48Spatrick   bool CopyNeedsCC = false;
20009467b48Spatrick   int ExtraOpc = 0;
20109467b48Spatrick   unsigned ExtraBits = 0;
20209467b48Spatrick   unsigned ExtraScale = 1;
20309467b48Spatrick   bool ExtraNeedsCC = false;
20409467b48Spatrick 
20509467b48Spatrick   // Strategy:
20609467b48Spatrick   // We need to select two types of instruction, maximizing the available
20709467b48Spatrick   // immediate range of each. The instructions we use will depend on whether
20809467b48Spatrick   // DestReg and BaseReg are low, high or the stack pointer.
20909467b48Spatrick   // * CopyOpc  - DestReg = BaseReg + imm
21009467b48Spatrick   //              This will be emitted once if DestReg != BaseReg, and never if
21109467b48Spatrick   //              DestReg == BaseReg.
21209467b48Spatrick   // * ExtraOpc - DestReg = DestReg + imm
21309467b48Spatrick   //              This will be emitted as many times as necessary to add the
21409467b48Spatrick   //              full immediate.
21509467b48Spatrick   // If the immediate ranges of these instructions are not large enough to cover
21609467b48Spatrick   // NumBytes with a reasonable number of instructions, we fall back to using a
21709467b48Spatrick   // value loaded from a constant pool.
21809467b48Spatrick   if (DestReg == ARM::SP) {
21909467b48Spatrick     if (BaseReg == ARM::SP) {
22009467b48Spatrick       // sp -> sp
22109467b48Spatrick       // Already in right reg, no copy needed
22209467b48Spatrick     } else {
22309467b48Spatrick       // low -> sp or high -> sp
22409467b48Spatrick       CopyOpc = ARM::tMOVr;
22509467b48Spatrick       CopyBits = 0;
22609467b48Spatrick     }
22709467b48Spatrick     ExtraOpc = isSub ? ARM::tSUBspi : ARM::tADDspi;
22809467b48Spatrick     ExtraBits = 7;
22909467b48Spatrick     ExtraScale = 4;
23009467b48Spatrick   } else if (isARMLowRegister(DestReg)) {
23109467b48Spatrick     if (BaseReg == ARM::SP) {
23209467b48Spatrick       // sp -> low
23309467b48Spatrick       assert(!isSub && "Thumb1 does not have tSUBrSPi");
23409467b48Spatrick       CopyOpc = ARM::tADDrSPi;
23509467b48Spatrick       CopyBits = 8;
23609467b48Spatrick       CopyScale = 4;
23709467b48Spatrick     } else if (DestReg == BaseReg) {
23809467b48Spatrick       // low -> same low
23909467b48Spatrick       // Already in right reg, no copy needed
24009467b48Spatrick     } else if (isARMLowRegister(BaseReg)) {
24109467b48Spatrick       // low -> different low
24209467b48Spatrick       CopyOpc = isSub ? ARM::tSUBi3 : ARM::tADDi3;
24309467b48Spatrick       CopyBits = 3;
24409467b48Spatrick       CopyNeedsCC = true;
24509467b48Spatrick     } else {
24609467b48Spatrick       // high -> low
24709467b48Spatrick       CopyOpc = ARM::tMOVr;
24809467b48Spatrick       CopyBits = 0;
24909467b48Spatrick     }
25009467b48Spatrick     ExtraOpc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
25109467b48Spatrick     ExtraBits = 8;
25209467b48Spatrick     ExtraNeedsCC = true;
25309467b48Spatrick   } else /* DestReg is high */ {
25409467b48Spatrick     if (DestReg == BaseReg) {
25509467b48Spatrick       // high -> same high
25609467b48Spatrick       // Already in right reg, no copy needed
25709467b48Spatrick     } else {
25809467b48Spatrick       // {low,high,sp} -> high
25909467b48Spatrick       CopyOpc = ARM::tMOVr;
26009467b48Spatrick       CopyBits = 0;
26109467b48Spatrick     }
26209467b48Spatrick     ExtraOpc = 0;
26309467b48Spatrick   }
26409467b48Spatrick 
26509467b48Spatrick   // We could handle an unaligned immediate with an unaligned copy instruction
26609467b48Spatrick   // and an aligned extra instruction, but this case is not currently needed.
26709467b48Spatrick   assert(((Bytes & 3) == 0 || ExtraScale == 1) &&
26809467b48Spatrick          "Unaligned offset, but all instructions require alignment");
26909467b48Spatrick 
27009467b48Spatrick   unsigned CopyRange = ((1 << CopyBits) - 1) * CopyScale;
27109467b48Spatrick   // If we would emit the copy with an immediate of 0, just use tMOVr.
27209467b48Spatrick   if (CopyOpc && Bytes < CopyScale) {
27309467b48Spatrick     CopyOpc = ARM::tMOVr;
27409467b48Spatrick     CopyScale = 1;
27509467b48Spatrick     CopyNeedsCC = false;
27609467b48Spatrick     CopyRange = 0;
27709467b48Spatrick   }
27809467b48Spatrick   unsigned ExtraRange = ((1 << ExtraBits) - 1) * ExtraScale; // per instruction
27909467b48Spatrick   unsigned RequiredCopyInstrs = CopyOpc ? 1 : 0;
28009467b48Spatrick   unsigned RangeAfterCopy = (CopyRange > Bytes) ? 0 : (Bytes - CopyRange);
28109467b48Spatrick 
28209467b48Spatrick   // We could handle this case when the copy instruction does not require an
28309467b48Spatrick   // aligned immediate, but we do not currently do this.
28409467b48Spatrick   assert(RangeAfterCopy % ExtraScale == 0 &&
28509467b48Spatrick          "Extra instruction requires immediate to be aligned");
28609467b48Spatrick 
28709467b48Spatrick   unsigned RequiredExtraInstrs;
28809467b48Spatrick   if (ExtraRange)
28909467b48Spatrick     RequiredExtraInstrs = alignTo(RangeAfterCopy, ExtraRange) / ExtraRange;
29009467b48Spatrick   else if (RangeAfterCopy > 0)
29109467b48Spatrick     // We need an extra instruction but none is available
29209467b48Spatrick     RequiredExtraInstrs = 1000000;
29309467b48Spatrick   else
29409467b48Spatrick     RequiredExtraInstrs = 0;
29509467b48Spatrick   unsigned RequiredInstrs = RequiredCopyInstrs + RequiredExtraInstrs;
29609467b48Spatrick   unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2;
29709467b48Spatrick 
29809467b48Spatrick   // Use a constant pool, if the sequence of ADDs/SUBs is too expensive.
29909467b48Spatrick   if (RequiredInstrs > Threshold) {
30009467b48Spatrick     emitThumbRegPlusImmInReg(MBB, MBBI, dl,
30109467b48Spatrick                              DestReg, BaseReg, NumBytes, true,
30209467b48Spatrick                              TII, MRI, MIFlags);
30309467b48Spatrick     return;
30409467b48Spatrick   }
30509467b48Spatrick 
30609467b48Spatrick   // Emit zero or one copy instructions
30709467b48Spatrick   if (CopyOpc) {
30809467b48Spatrick     unsigned CopyImm = std::min(Bytes, CopyRange) / CopyScale;
30909467b48Spatrick     Bytes -= CopyImm * CopyScale;
31009467b48Spatrick 
31109467b48Spatrick     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(CopyOpc), DestReg);
31209467b48Spatrick     if (CopyNeedsCC)
31309467b48Spatrick       MIB = MIB.add(t1CondCodeOp());
31409467b48Spatrick     MIB.addReg(BaseReg, RegState::Kill);
31509467b48Spatrick     if (CopyOpc != ARM::tMOVr) {
31609467b48Spatrick       MIB.addImm(CopyImm);
31709467b48Spatrick     }
31809467b48Spatrick     MIB.setMIFlags(MIFlags).add(predOps(ARMCC::AL));
31909467b48Spatrick 
32009467b48Spatrick     BaseReg = DestReg;
32109467b48Spatrick   }
32209467b48Spatrick 
32309467b48Spatrick   // Emit zero or more in-place add/sub instructions
32409467b48Spatrick   while (Bytes) {
32509467b48Spatrick     unsigned ExtraImm = std::min(Bytes, ExtraRange) / ExtraScale;
32609467b48Spatrick     Bytes -= ExtraImm * ExtraScale;
32709467b48Spatrick 
32809467b48Spatrick     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(ExtraOpc), DestReg);
32909467b48Spatrick     if (ExtraNeedsCC)
33009467b48Spatrick       MIB = MIB.add(t1CondCodeOp());
33109467b48Spatrick     MIB.addReg(BaseReg)
33209467b48Spatrick        .addImm(ExtraImm)
33309467b48Spatrick        .add(predOps(ARMCC::AL))
33409467b48Spatrick        .setMIFlags(MIFlags);
33509467b48Spatrick   }
33609467b48Spatrick }
33709467b48Spatrick 
removeOperands(MachineInstr & MI,unsigned i)33809467b48Spatrick static void removeOperands(MachineInstr &MI, unsigned i) {
33909467b48Spatrick   unsigned Op = i;
34009467b48Spatrick   for (unsigned e = MI.getNumOperands(); i != e; ++i)
341*d415bd75Srobert     MI.removeOperand(Op);
34209467b48Spatrick }
34309467b48Spatrick 
34409467b48Spatrick /// convertToNonSPOpcode - Change the opcode to the non-SP version, because
34509467b48Spatrick /// we're replacing the frame index with a non-SP register.
convertToNonSPOpcode(unsigned Opcode)34609467b48Spatrick static unsigned convertToNonSPOpcode(unsigned Opcode) {
34709467b48Spatrick   switch (Opcode) {
34809467b48Spatrick   case ARM::tLDRspi:
34909467b48Spatrick     return ARM::tLDRi;
35009467b48Spatrick 
35109467b48Spatrick   case ARM::tSTRspi:
35209467b48Spatrick     return ARM::tSTRi;
35309467b48Spatrick   }
35409467b48Spatrick 
35509467b48Spatrick   return Opcode;
35609467b48Spatrick }
35709467b48Spatrick 
rewriteFrameIndex(MachineBasicBlock::iterator II,unsigned FrameRegIdx,Register FrameReg,int & Offset,const ARMBaseInstrInfo & TII) const35809467b48Spatrick bool ThumbRegisterInfo::rewriteFrameIndex(MachineBasicBlock::iterator II,
35909467b48Spatrick                                           unsigned FrameRegIdx,
360097a140dSpatrick                                           Register FrameReg, int &Offset,
36109467b48Spatrick                                           const ARMBaseInstrInfo &TII) const {
36209467b48Spatrick   MachineInstr &MI = *II;
36309467b48Spatrick   MachineBasicBlock &MBB = *MI.getParent();
364*d415bd75Srobert   MachineFunction &MF = *MBB.getParent();
36509467b48Spatrick   assert(MBB.getParent()->getSubtarget<ARMSubtarget>().isThumb1Only() &&
36609467b48Spatrick          "This isn't needed for thumb2!");
36709467b48Spatrick   DebugLoc dl = MI.getDebugLoc();
36809467b48Spatrick   MachineInstrBuilder MIB(*MBB.getParent(), &MI);
36909467b48Spatrick   unsigned Opcode = MI.getOpcode();
37009467b48Spatrick   const MCInstrDesc &Desc = MI.getDesc();
37109467b48Spatrick   unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
37209467b48Spatrick 
37309467b48Spatrick   if (Opcode == ARM::tADDframe) {
37409467b48Spatrick     Offset += MI.getOperand(FrameRegIdx+1).getImm();
37509467b48Spatrick     Register DestReg = MI.getOperand(0).getReg();
37609467b48Spatrick 
37709467b48Spatrick     emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII,
37809467b48Spatrick                               *this);
37909467b48Spatrick     MBB.erase(II);
38009467b48Spatrick     return true;
38109467b48Spatrick   } else {
38209467b48Spatrick     if (AddrMode != ARMII::AddrModeT1_s)
38309467b48Spatrick       llvm_unreachable("Unsupported addressing mode!");
38409467b48Spatrick 
38509467b48Spatrick     unsigned ImmIdx = FrameRegIdx + 1;
38609467b48Spatrick     int InstrOffs = MI.getOperand(ImmIdx).getImm();
38709467b48Spatrick     unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5;
38809467b48Spatrick     unsigned Scale = 4;
38909467b48Spatrick 
39009467b48Spatrick     Offset += InstrOffs * Scale;
39109467b48Spatrick     assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!");
39209467b48Spatrick 
39309467b48Spatrick     // Common case: small offset, fits into instruction.
39409467b48Spatrick     MachineOperand &ImmOp = MI.getOperand(ImmIdx);
39509467b48Spatrick     int ImmedOffset = Offset / Scale;
39609467b48Spatrick     unsigned Mask = (1 << NumBits) - 1;
39709467b48Spatrick 
39809467b48Spatrick     if ((unsigned)Offset <= Mask * Scale) {
39909467b48Spatrick       // Replace the FrameIndex with the frame register (e.g., sp).
400*d415bd75Srobert       Register DestReg = FrameReg;
401*d415bd75Srobert 
402*d415bd75Srobert       // In case FrameReg is a high register, move it to a low reg to ensure it
403*d415bd75Srobert       // can be used as an operand.
404*d415bd75Srobert       if (ARM::hGPRRegClass.contains(FrameReg) && FrameReg != ARM::SP) {
405*d415bd75Srobert         DestReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);
406*d415bd75Srobert         BuildMI(MBB, II, dl, TII.get(ARM::tMOVr), DestReg)
407*d415bd75Srobert             .addReg(FrameReg)
408*d415bd75Srobert             .add(predOps(ARMCC::AL));
409*d415bd75Srobert       }
410*d415bd75Srobert 
411*d415bd75Srobert       MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false);
41209467b48Spatrick       ImmOp.ChangeToImmediate(ImmedOffset);
41309467b48Spatrick 
41409467b48Spatrick       // If we're using a register where sp was stored, convert the instruction
41509467b48Spatrick       // to the non-SP version.
41609467b48Spatrick       unsigned NewOpc = convertToNonSPOpcode(Opcode);
41709467b48Spatrick       if (NewOpc != Opcode && FrameReg != ARM::SP)
41809467b48Spatrick         MI.setDesc(TII.get(NewOpc));
41909467b48Spatrick 
42009467b48Spatrick       return true;
42109467b48Spatrick     }
42209467b48Spatrick 
42309467b48Spatrick     NumBits = 5;
42409467b48Spatrick     Mask = (1 << NumBits) - 1;
42509467b48Spatrick 
42609467b48Spatrick     // If this is a thumb spill / restore, we will be using a constpool load to
42709467b48Spatrick     // materialize the offset.
42809467b48Spatrick     if (Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {
42909467b48Spatrick       ImmOp.ChangeToImmediate(0);
43009467b48Spatrick     } else {
43109467b48Spatrick       // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
43209467b48Spatrick       ImmedOffset = ImmedOffset & Mask;
43309467b48Spatrick       ImmOp.ChangeToImmediate(ImmedOffset);
43409467b48Spatrick       Offset &= ~(Mask * Scale);
43509467b48Spatrick     }
43609467b48Spatrick   }
43709467b48Spatrick 
43809467b48Spatrick   return Offset == 0;
43909467b48Spatrick }
44009467b48Spatrick 
resolveFrameIndex(MachineInstr & MI,Register BaseReg,int64_t Offset) const441097a140dSpatrick void ThumbRegisterInfo::resolveFrameIndex(MachineInstr &MI, Register BaseReg,
44209467b48Spatrick                                           int64_t Offset) const {
44309467b48Spatrick   const MachineFunction &MF = *MI.getParent()->getParent();
44409467b48Spatrick   const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
44509467b48Spatrick   if (!STI.isThumb1Only())
44609467b48Spatrick     return ARMBaseRegisterInfo::resolveFrameIndex(MI, BaseReg, Offset);
44709467b48Spatrick 
44809467b48Spatrick   const ARMBaseInstrInfo &TII = *STI.getInstrInfo();
44909467b48Spatrick   int Off = Offset; // ARM doesn't need the general 64-bit offsets
45009467b48Spatrick   unsigned i = 0;
45109467b48Spatrick 
45209467b48Spatrick   while (!MI.getOperand(i).isFI()) {
45309467b48Spatrick     ++i;
45409467b48Spatrick     assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
45509467b48Spatrick   }
45609467b48Spatrick   bool Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII);
45709467b48Spatrick   assert (Done && "Unable to resolve frame index!");
45809467b48Spatrick   (void)Done;
45909467b48Spatrick }
46009467b48Spatrick 
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const461*d415bd75Srobert bool ThumbRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
46209467b48Spatrick                                             int SPAdj, unsigned FIOperandNum,
46309467b48Spatrick                                             RegScavenger *RS) const {
46409467b48Spatrick   MachineInstr &MI = *II;
46509467b48Spatrick   MachineBasicBlock &MBB = *MI.getParent();
46609467b48Spatrick   MachineFunction &MF = *MBB.getParent();
46709467b48Spatrick   const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
46809467b48Spatrick   if (!STI.isThumb1Only())
46909467b48Spatrick     return ARMBaseRegisterInfo::eliminateFrameIndex(II, SPAdj, FIOperandNum,
47009467b48Spatrick                                                     RS);
47109467b48Spatrick 
472097a140dSpatrick   Register VReg;
47309467b48Spatrick   const ARMBaseInstrInfo &TII = *STI.getInstrInfo();
47409467b48Spatrick   DebugLoc dl = MI.getDebugLoc();
47509467b48Spatrick   MachineInstrBuilder MIB(*MBB.getParent(), &MI);
47609467b48Spatrick 
477097a140dSpatrick   Register FrameReg;
47809467b48Spatrick   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
47909467b48Spatrick   const ARMFrameLowering *TFI = getFrameLowering(MF);
48009467b48Spatrick   int Offset = TFI->ResolveFrameIndexReference(MF, FrameIndex, FrameReg, SPAdj);
48109467b48Spatrick 
48209467b48Spatrick   // PEI::scavengeFrameVirtualRegs() cannot accurately track SPAdj because the
48309467b48Spatrick   // call frame setup/destroy instructions have already been eliminated.  That
48409467b48Spatrick   // means the stack pointer cannot be used to access the emergency spill slot
48509467b48Spatrick   // when !hasReservedCallFrame().
48609467b48Spatrick #ifndef NDEBUG
48709467b48Spatrick   if (RS && FrameReg == ARM::SP && RS->isScavengingFrameIndex(FrameIndex)){
48809467b48Spatrick     assert(STI.getFrameLowering()->hasReservedCallFrame(MF) &&
48909467b48Spatrick            "Cannot use SP to access the emergency spill slot in "
49009467b48Spatrick            "functions without a reserved call frame");
49109467b48Spatrick     assert(!MF.getFrameInfo().hasVarSizedObjects() &&
49209467b48Spatrick            "Cannot use SP to access the emergency spill slot in "
49309467b48Spatrick            "functions with variable sized frame objects");
49409467b48Spatrick   }
49509467b48Spatrick #endif // NDEBUG
49609467b48Spatrick 
49709467b48Spatrick   // Special handling of dbg_value instructions.
49809467b48Spatrick   if (MI.isDebugValue()) {
49909467b48Spatrick     MI.getOperand(FIOperandNum).  ChangeToRegister(FrameReg, false /*isDef*/);
50009467b48Spatrick     MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
501*d415bd75Srobert     return false;
50209467b48Spatrick   }
50309467b48Spatrick 
50409467b48Spatrick   // Modify MI as necessary to handle as much of 'Offset' as possible
50509467b48Spatrick   assert(MF.getInfo<ARMFunctionInfo>()->isThumbFunction() &&
50609467b48Spatrick          "This eliminateFrameIndex only supports Thumb1!");
50709467b48Spatrick   if (rewriteFrameIndex(MI, FIOperandNum, FrameReg, Offset, TII))
508*d415bd75Srobert     return true;
50909467b48Spatrick 
51009467b48Spatrick   // If we get here, the immediate doesn't fit into the instruction.  We folded
51109467b48Spatrick   // as much as possible above, handle the rest, providing a register that is
51209467b48Spatrick   // SP+LargeImm.
51309467b48Spatrick   assert(Offset && "This code isn't needed if offset already handled!");
51409467b48Spatrick 
51509467b48Spatrick   unsigned Opcode = MI.getOpcode();
51609467b48Spatrick 
51709467b48Spatrick   // Remove predicate first.
51809467b48Spatrick   int PIdx = MI.findFirstPredOperandIdx();
51909467b48Spatrick   if (PIdx != -1)
52009467b48Spatrick     removeOperands(MI, PIdx);
52109467b48Spatrick 
52209467b48Spatrick   if (MI.mayLoad()) {
52309467b48Spatrick     // Use the destination register to materialize sp + offset.
52409467b48Spatrick     Register TmpReg = MI.getOperand(0).getReg();
52509467b48Spatrick     bool UseRR = false;
52609467b48Spatrick     if (Opcode == ARM::tLDRspi) {
52709467b48Spatrick       if (FrameReg == ARM::SP || STI.genExecuteOnly())
52809467b48Spatrick         emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg,
52909467b48Spatrick                                  Offset, false, TII, *this);
53009467b48Spatrick       else {
53109467b48Spatrick         emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset);
532*d415bd75Srobert         if (!ARM::hGPRRegClass.contains(FrameReg)) {
53309467b48Spatrick           UseRR = true;
534*d415bd75Srobert         } else {
535*d415bd75Srobert           // If FrameReg is a high register, add the reg values in a separate
536*d415bd75Srobert           // instruction as the load won't be able to access it.
537*d415bd75Srobert           BuildMI(MBB, II, dl, TII.get(ARM::tADDhirr), TmpReg)
538*d415bd75Srobert               .addReg(TmpReg)
539*d415bd75Srobert               .addReg(FrameReg)
540*d415bd75Srobert               .add(predOps(ARMCC::AL));
541*d415bd75Srobert         }
54209467b48Spatrick       }
54309467b48Spatrick     } else {
54409467b48Spatrick       emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII,
54509467b48Spatrick                                 *this);
54609467b48Spatrick     }
54709467b48Spatrick 
54809467b48Spatrick     MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi));
54909467b48Spatrick     MI.getOperand(FIOperandNum).ChangeToRegister(TmpReg, false, false, true);
550*d415bd75Srobert     if (UseRR) {
551*d415bd75Srobert       assert(!ARM::hGPRRegClass.contains(FrameReg) &&
552*d415bd75Srobert              "Thumb1 loads can't use high register");
55309467b48Spatrick       // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
55409467b48Spatrick       // register. The offset is already handled in the vreg value.
55509467b48Spatrick       MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false,
55609467b48Spatrick                                                      false);
557*d415bd75Srobert     }
55809467b48Spatrick   } else if (MI.mayStore()) {
55909467b48Spatrick       VReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);
56009467b48Spatrick       bool UseRR = false;
56109467b48Spatrick 
56209467b48Spatrick       if (Opcode == ARM::tSTRspi) {
56309467b48Spatrick         if (FrameReg == ARM::SP || STI.genExecuteOnly())
56409467b48Spatrick           emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg,
56509467b48Spatrick                                    Offset, false, TII, *this);
56609467b48Spatrick         else {
56709467b48Spatrick           emitLoadConstPool(MBB, II, dl, VReg, 0, Offset);
568*d415bd75Srobert           if (!ARM::hGPRRegClass.contains(FrameReg)) {
56909467b48Spatrick             UseRR = true;
570*d415bd75Srobert           } else {
571*d415bd75Srobert             // If FrameReg is a high register, add the reg values in a separate
572*d415bd75Srobert             // instruction as the load won't be able to access it.
573*d415bd75Srobert             BuildMI(MBB, II, dl, TII.get(ARM::tADDhirr), VReg)
574*d415bd75Srobert                 .addReg(VReg)
575*d415bd75Srobert                 .addReg(FrameReg)
576*d415bd75Srobert                 .add(predOps(ARMCC::AL));
577*d415bd75Srobert           }
57809467b48Spatrick         }
57909467b48Spatrick       } else
58009467b48Spatrick         emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII,
58109467b48Spatrick                                   *this);
58209467b48Spatrick       MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi));
58309467b48Spatrick       MI.getOperand(FIOperandNum).ChangeToRegister(VReg, false, false, true);
584*d415bd75Srobert       if (UseRR) {
585*d415bd75Srobert         assert(!ARM::hGPRRegClass.contains(FrameReg) &&
586*d415bd75Srobert                "Thumb1 stores can't use high register");
58709467b48Spatrick         // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
58809467b48Spatrick         // register. The offset is already handled in the vreg value.
58909467b48Spatrick         MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false,
59009467b48Spatrick                                                        false);
591*d415bd75Srobert       }
59209467b48Spatrick   } else {
59309467b48Spatrick     llvm_unreachable("Unexpected opcode!");
59409467b48Spatrick   }
59509467b48Spatrick 
59609467b48Spatrick   // Add predicate back if it's needed.
59709467b48Spatrick   if (MI.isPredicable())
59809467b48Spatrick     MIB.add(predOps(ARMCC::AL));
599*d415bd75Srobert   return false;
60009467b48Spatrick }
60109467b48Spatrick 
60209467b48Spatrick bool
useFPForScavengingIndex(const MachineFunction & MF) const60309467b48Spatrick ThumbRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
60409467b48Spatrick   if (MF.getSubtarget<ARMSubtarget>().isThumb1Only()) {
60509467b48Spatrick     // For Thumb1, the emergency spill slot must be some small positive
60609467b48Spatrick     // offset from the base/stack pointer.
60709467b48Spatrick     return false;
60809467b48Spatrick   }
60909467b48Spatrick   // For Thumb2, put the emergency spill slot next to FP.
61009467b48Spatrick   return true;
61109467b48Spatrick }
612