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