1283625Sdim//===-- ThumbRegisterInfo.cpp - Thumb-1 Register Information -------------===// 2283625Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6283625Sdim// 7283625Sdim//===----------------------------------------------------------------------===// 8283625Sdim// 9283625Sdim// This file contains the Thumb-1 implementation of the TargetRegisterInfo 10283625Sdim// class. 11283625Sdim// 12283625Sdim//===----------------------------------------------------------------------===// 13283625Sdim 14283625Sdim#include "ThumbRegisterInfo.h" 15283625Sdim#include "ARMBaseInstrInfo.h" 16283625Sdim#include "ARMMachineFunctionInfo.h" 17283625Sdim#include "ARMSubtarget.h" 18283625Sdim#include "MCTargetDesc/ARMAddressingModes.h" 19283625Sdim#include "llvm/CodeGen/MachineConstantPool.h" 20283625Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 21283625Sdim#include "llvm/CodeGen/MachineFunction.h" 22283625Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 23283625Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 24283625Sdim#include "llvm/CodeGen/RegisterScavenging.h" 25283625Sdim#include "llvm/IR/Constants.h" 26283625Sdim#include "llvm/IR/DerivedTypes.h" 27283625Sdim#include "llvm/IR/Function.h" 28283625Sdim#include "llvm/IR/LLVMContext.h" 29283625Sdim#include "llvm/Support/CommandLine.h" 30283625Sdim#include "llvm/Support/ErrorHandling.h" 31327952Sdim#include "llvm/CodeGen/TargetFrameLowering.h" 32283625Sdim#include "llvm/Target/TargetMachine.h" 33283625Sdim 34283625Sdimnamespace llvm { 35283625Sdimextern cl::opt<bool> ReuseFrameIndexVals; 36283625Sdim} 37283625Sdim 38283625Sdimusing namespace llvm; 39283625Sdim 40283625SdimThumbRegisterInfo::ThumbRegisterInfo() : ARMBaseRegisterInfo() {} 41283625Sdim 42283625Sdimconst TargetRegisterClass * 43283625SdimThumbRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC, 44283625Sdim const MachineFunction &MF) const { 45283625Sdim if (!MF.getSubtarget<ARMSubtarget>().isThumb1Only()) 46283625Sdim return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC, MF); 47283625Sdim 48283625Sdim if (ARM::tGPRRegClass.hasSubClassEq(RC)) 49283625Sdim return &ARM::tGPRRegClass; 50283625Sdim return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC, MF); 51283625Sdim} 52283625Sdim 53283625Sdimconst TargetRegisterClass * 54283625SdimThumbRegisterInfo::getPointerRegClass(const MachineFunction &MF, 55283625Sdim unsigned Kind) const { 56283625Sdim if (!MF.getSubtarget<ARMSubtarget>().isThumb1Only()) 57283625Sdim return ARMBaseRegisterInfo::getPointerRegClass(MF, Kind); 58283625Sdim return &ARM::tGPRRegClass; 59283625Sdim} 60283625Sdim 61283625Sdimstatic void emitThumb1LoadConstPool(MachineBasicBlock &MBB, 62283625Sdim MachineBasicBlock::iterator &MBBI, 63309124Sdim const DebugLoc &dl, unsigned DestReg, 64283625Sdim unsigned SubIdx, int Val, 65283625Sdim ARMCC::CondCodes Pred, unsigned PredReg, 66283625Sdim unsigned MIFlags) { 67283625Sdim MachineFunction &MF = *MBB.getParent(); 68283625Sdim const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>(); 69283625Sdim const TargetInstrInfo &TII = *STI.getInstrInfo(); 70283625Sdim MachineConstantPool *ConstantPool = MF.getConstantPool(); 71283625Sdim const Constant *C = ConstantInt::get( 72327952Sdim Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), Val); 73283625Sdim unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); 74283625Sdim 75283625Sdim BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRpci)) 76283625Sdim .addReg(DestReg, getDefRegState(true), SubIdx) 77283625Sdim .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg) 78283625Sdim .setMIFlags(MIFlags); 79283625Sdim} 80283625Sdim 81283625Sdimstatic void emitThumb2LoadConstPool(MachineBasicBlock &MBB, 82283625Sdim MachineBasicBlock::iterator &MBBI, 83309124Sdim const DebugLoc &dl, unsigned DestReg, 84283625Sdim unsigned SubIdx, int Val, 85283625Sdim ARMCC::CondCodes Pred, unsigned PredReg, 86283625Sdim unsigned MIFlags) { 87283625Sdim MachineFunction &MF = *MBB.getParent(); 88283625Sdim const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); 89283625Sdim MachineConstantPool *ConstantPool = MF.getConstantPool(); 90283625Sdim const Constant *C = ConstantInt::get( 91327952Sdim Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), Val); 92283625Sdim unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); 93283625Sdim 94283625Sdim BuildMI(MBB, MBBI, dl, TII.get(ARM::t2LDRpci)) 95321369Sdim .addReg(DestReg, getDefRegState(true), SubIdx) 96321369Sdim .addConstantPoolIndex(Idx) 97321369Sdim .add(predOps(ARMCC::AL)) 98321369Sdim .setMIFlags(MIFlags); 99283625Sdim} 100283625Sdim 101283625Sdim/// emitLoadConstPool - Emits a load from constpool to materialize the 102283625Sdim/// specified immediate. 103283625Sdimvoid ThumbRegisterInfo::emitLoadConstPool( 104309124Sdim MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, 105309124Sdim const DebugLoc &dl, unsigned DestReg, unsigned SubIdx, int Val, 106309124Sdim ARMCC::CondCodes Pred, unsigned PredReg, unsigned MIFlags) const { 107283625Sdim MachineFunction &MF = *MBB.getParent(); 108283625Sdim const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>(); 109283625Sdim if (STI.isThumb1Only()) { 110360784Sdim assert( 111360784Sdim (isARMLowRegister(DestReg) || Register::isVirtualRegister(DestReg)) && 112360784Sdim "Thumb1 does not have ldr to high register"); 113283625Sdim return emitThumb1LoadConstPool(MBB, MBBI, dl, DestReg, SubIdx, Val, Pred, 114283625Sdim PredReg, MIFlags); 115283625Sdim } 116283625Sdim return emitThumb2LoadConstPool(MBB, MBBI, dl, DestReg, SubIdx, Val, Pred, 117283625Sdim PredReg, MIFlags); 118283625Sdim} 119283625Sdim 120283625Sdim/// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize 121283625Sdim/// a destreg = basereg + immediate in Thumb code. Materialize the immediate 122283625Sdim/// in a register using mov / mvn sequences or load the immediate from a 123283625Sdim/// constpool entry. 124309124Sdimstatic void emitThumbRegPlusImmInReg( 125309124Sdim MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, 126309124Sdim const DebugLoc &dl, unsigned DestReg, unsigned BaseReg, int NumBytes, 127309124Sdim bool CanChangeCC, const TargetInstrInfo &TII, 128309124Sdim const ARMBaseRegisterInfo &MRI, unsigned MIFlags = MachineInstr::NoFlags) { 129309124Sdim MachineFunction &MF = *MBB.getParent(); 130314564Sdim const ARMSubtarget &ST = MF.getSubtarget<ARMSubtarget>(); 131309124Sdim bool isHigh = !isARMLowRegister(DestReg) || 132309124Sdim (BaseReg != 0 && !isARMLowRegister(BaseReg)); 133309124Sdim bool isSub = false; 134309124Sdim // Subtract doesn't have high register version. Load the negative value 135309124Sdim // if either base or dest register is a high register. Also, if do not 136309124Sdim // issue sub as part of the sequence if condition register is to be 137309124Sdim // preserved. 138309124Sdim if (NumBytes < 0 && !isHigh && CanChangeCC) { 139309124Sdim isSub = true; 140309124Sdim NumBytes = -NumBytes; 141309124Sdim } 142309124Sdim unsigned LdReg = DestReg; 143309124Sdim if (DestReg == ARM::SP) 144309124Sdim assert(BaseReg == ARM::SP && "Unexpected!"); 145360784Sdim if (!isARMLowRegister(DestReg) && !Register::isVirtualRegister(DestReg)) 146309124Sdim LdReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass); 147283625Sdim 148309124Sdim if (NumBytes <= 255 && NumBytes >= 0 && CanChangeCC) { 149321369Sdim BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg) 150321369Sdim .add(t1CondCodeOp()) 151309124Sdim .addImm(NumBytes) 152309124Sdim .setMIFlags(MIFlags); 153309124Sdim } else if (NumBytes < 0 && NumBytes >= -255 && CanChangeCC) { 154321369Sdim BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg) 155321369Sdim .add(t1CondCodeOp()) 156309124Sdim .addImm(NumBytes) 157309124Sdim .setMIFlags(MIFlags); 158321369Sdim BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg) 159321369Sdim .add(t1CondCodeOp()) 160309124Sdim .addReg(LdReg, RegState::Kill) 161309124Sdim .setMIFlags(MIFlags); 162314564Sdim } else if (ST.genExecuteOnly()) { 163314564Sdim BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), LdReg) 164314564Sdim .addImm(NumBytes).setMIFlags(MIFlags); 165309124Sdim } else 166309124Sdim MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes, ARMCC::AL, 0, 167309124Sdim MIFlags); 168283625Sdim 169309124Sdim // Emit add / sub. 170309124Sdim int Opc = (isSub) ? ARM::tSUBrr 171309124Sdim : ((isHigh || !CanChangeCC) ? ARM::tADDhirr : ARM::tADDrr); 172309124Sdim MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); 173309124Sdim if (Opc != ARM::tADDhirr) 174321369Sdim MIB = MIB.add(t1CondCodeOp()); 175309124Sdim if (DestReg == ARM::SP || isSub) 176309124Sdim MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill); 177309124Sdim else 178309124Sdim MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill); 179321369Sdim MIB.add(predOps(ARMCC::AL)); 180283625Sdim} 181283625Sdim 182283625Sdim/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize 183283625Sdim/// a destreg = basereg + immediate in Thumb code. Tries a series of ADDs or 184283625Sdim/// SUBs first, and uses a constant pool value if the instruction sequence would 185283625Sdim/// be too long. This is allowed to modify the condition flags. 186283625Sdimvoid llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, 187283625Sdim MachineBasicBlock::iterator &MBBI, 188309124Sdim const DebugLoc &dl, unsigned DestReg, 189309124Sdim unsigned BaseReg, int NumBytes, 190309124Sdim const TargetInstrInfo &TII, 191309124Sdim const ARMBaseRegisterInfo &MRI, 192283625Sdim unsigned MIFlags) { 193283625Sdim bool isSub = NumBytes < 0; 194283625Sdim unsigned Bytes = (unsigned)NumBytes; 195283625Sdim if (isSub) Bytes = -NumBytes; 196283625Sdim 197283625Sdim int CopyOpc = 0; 198283625Sdim unsigned CopyBits = 0; 199283625Sdim unsigned CopyScale = 1; 200283625Sdim bool CopyNeedsCC = false; 201283625Sdim int ExtraOpc = 0; 202283625Sdim unsigned ExtraBits = 0; 203283625Sdim unsigned ExtraScale = 1; 204283625Sdim bool ExtraNeedsCC = false; 205283625Sdim 206283625Sdim // Strategy: 207283625Sdim // We need to select two types of instruction, maximizing the available 208283625Sdim // immediate range of each. The instructions we use will depend on whether 209283625Sdim // DestReg and BaseReg are low, high or the stack pointer. 210283625Sdim // * CopyOpc - DestReg = BaseReg + imm 211283625Sdim // This will be emitted once if DestReg != BaseReg, and never if 212283625Sdim // DestReg == BaseReg. 213283625Sdim // * ExtraOpc - DestReg = DestReg + imm 214283625Sdim // This will be emitted as many times as necessary to add the 215283625Sdim // full immediate. 216283625Sdim // If the immediate ranges of these instructions are not large enough to cover 217283625Sdim // NumBytes with a reasonable number of instructions, we fall back to using a 218283625Sdim // value loaded from a constant pool. 219283625Sdim if (DestReg == ARM::SP) { 220283625Sdim if (BaseReg == ARM::SP) { 221283625Sdim // sp -> sp 222283625Sdim // Already in right reg, no copy needed 223283625Sdim } else { 224283625Sdim // low -> sp or high -> sp 225283625Sdim CopyOpc = ARM::tMOVr; 226283625Sdim CopyBits = 0; 227283625Sdim } 228283625Sdim ExtraOpc = isSub ? ARM::tSUBspi : ARM::tADDspi; 229283625Sdim ExtraBits = 7; 230283625Sdim ExtraScale = 4; 231283625Sdim } else if (isARMLowRegister(DestReg)) { 232283625Sdim if (BaseReg == ARM::SP) { 233283625Sdim // sp -> low 234283625Sdim assert(!isSub && "Thumb1 does not have tSUBrSPi"); 235283625Sdim CopyOpc = ARM::tADDrSPi; 236283625Sdim CopyBits = 8; 237283625Sdim CopyScale = 4; 238283625Sdim } else if (DestReg == BaseReg) { 239283625Sdim // low -> same low 240283625Sdim // Already in right reg, no copy needed 241283625Sdim } else if (isARMLowRegister(BaseReg)) { 242283625Sdim // low -> different low 243283625Sdim CopyOpc = isSub ? ARM::tSUBi3 : ARM::tADDi3; 244283625Sdim CopyBits = 3; 245283625Sdim CopyNeedsCC = true; 246283625Sdim } else { 247283625Sdim // high -> low 248283625Sdim CopyOpc = ARM::tMOVr; 249283625Sdim CopyBits = 0; 250283625Sdim } 251283625Sdim ExtraOpc = isSub ? ARM::tSUBi8 : ARM::tADDi8; 252283625Sdim ExtraBits = 8; 253283625Sdim ExtraNeedsCC = true; 254283625Sdim } else /* DestReg is high */ { 255283625Sdim if (DestReg == BaseReg) { 256283625Sdim // high -> same high 257283625Sdim // Already in right reg, no copy needed 258283625Sdim } else { 259283625Sdim // {low,high,sp} -> high 260283625Sdim CopyOpc = ARM::tMOVr; 261283625Sdim CopyBits = 0; 262283625Sdim } 263283625Sdim ExtraOpc = 0; 264283625Sdim } 265283625Sdim 266283625Sdim // We could handle an unaligned immediate with an unaligned copy instruction 267283625Sdim // and an aligned extra instruction, but this case is not currently needed. 268283625Sdim assert(((Bytes & 3) == 0 || ExtraScale == 1) && 269283625Sdim "Unaligned offset, but all instructions require alignment"); 270283625Sdim 271283625Sdim unsigned CopyRange = ((1 << CopyBits) - 1) * CopyScale; 272283625Sdim // If we would emit the copy with an immediate of 0, just use tMOVr. 273283625Sdim if (CopyOpc && Bytes < CopyScale) { 274283625Sdim CopyOpc = ARM::tMOVr; 275283625Sdim CopyScale = 1; 276283625Sdim CopyNeedsCC = false; 277283625Sdim CopyRange = 0; 278283625Sdim } 279283625Sdim unsigned ExtraRange = ((1 << ExtraBits) - 1) * ExtraScale; // per instruction 280283625Sdim unsigned RequiredCopyInstrs = CopyOpc ? 1 : 0; 281283625Sdim unsigned RangeAfterCopy = (CopyRange > Bytes) ? 0 : (Bytes - CopyRange); 282283625Sdim 283283625Sdim // We could handle this case when the copy instruction does not require an 284283625Sdim // aligned immediate, but we do not currently do this. 285283625Sdim assert(RangeAfterCopy % ExtraScale == 0 && 286283625Sdim "Extra instruction requires immediate to be aligned"); 287283625Sdim 288283625Sdim unsigned RequiredExtraInstrs; 289283625Sdim if (ExtraRange) 290309124Sdim RequiredExtraInstrs = alignTo(RangeAfterCopy, ExtraRange) / ExtraRange; 291283625Sdim else if (RangeAfterCopy > 0) 292283625Sdim // We need an extra instruction but none is available 293283625Sdim RequiredExtraInstrs = 1000000; 294283625Sdim else 295283625Sdim RequiredExtraInstrs = 0; 296283625Sdim unsigned RequiredInstrs = RequiredCopyInstrs + RequiredExtraInstrs; 297283625Sdim unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2; 298283625Sdim 299283625Sdim // Use a constant pool, if the sequence of ADDs/SUBs is too expensive. 300283625Sdim if (RequiredInstrs > Threshold) { 301283625Sdim emitThumbRegPlusImmInReg(MBB, MBBI, dl, 302283625Sdim DestReg, BaseReg, NumBytes, true, 303283625Sdim TII, MRI, MIFlags); 304283625Sdim return; 305283625Sdim } 306283625Sdim 307283625Sdim // Emit zero or one copy instructions 308283625Sdim if (CopyOpc) { 309283625Sdim unsigned CopyImm = std::min(Bytes, CopyRange) / CopyScale; 310283625Sdim Bytes -= CopyImm * CopyScale; 311283625Sdim 312283625Sdim MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(CopyOpc), DestReg); 313283625Sdim if (CopyNeedsCC) 314321369Sdim MIB = MIB.add(t1CondCodeOp()); 315283625Sdim MIB.addReg(BaseReg, RegState::Kill); 316283625Sdim if (CopyOpc != ARM::tMOVr) { 317283625Sdim MIB.addImm(CopyImm); 318283625Sdim } 319321369Sdim MIB.setMIFlags(MIFlags).add(predOps(ARMCC::AL)); 320283625Sdim 321283625Sdim BaseReg = DestReg; 322283625Sdim } 323283625Sdim 324283625Sdim // Emit zero or more in-place add/sub instructions 325283625Sdim while (Bytes) { 326283625Sdim unsigned ExtraImm = std::min(Bytes, ExtraRange) / ExtraScale; 327283625Sdim Bytes -= ExtraImm * ExtraScale; 328283625Sdim 329283625Sdim MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(ExtraOpc), DestReg); 330283625Sdim if (ExtraNeedsCC) 331321369Sdim MIB = MIB.add(t1CondCodeOp()); 332321369Sdim MIB.addReg(BaseReg) 333321369Sdim .addImm(ExtraImm) 334321369Sdim .add(predOps(ARMCC::AL)) 335321369Sdim .setMIFlags(MIFlags); 336283625Sdim } 337283625Sdim} 338283625Sdim 339283625Sdimstatic void removeOperands(MachineInstr &MI, unsigned i) { 340283625Sdim unsigned Op = i; 341283625Sdim for (unsigned e = MI.getNumOperands(); i != e; ++i) 342283625Sdim MI.RemoveOperand(Op); 343283625Sdim} 344283625Sdim 345283625Sdim/// convertToNonSPOpcode - Change the opcode to the non-SP version, because 346283625Sdim/// we're replacing the frame index with a non-SP register. 347283625Sdimstatic unsigned convertToNonSPOpcode(unsigned Opcode) { 348283625Sdim switch (Opcode) { 349283625Sdim case ARM::tLDRspi: 350283625Sdim return ARM::tLDRi; 351283625Sdim 352283625Sdim case ARM::tSTRspi: 353283625Sdim return ARM::tSTRi; 354283625Sdim } 355283625Sdim 356283625Sdim return Opcode; 357283625Sdim} 358283625Sdim 359283625Sdimbool ThumbRegisterInfo::rewriteFrameIndex(MachineBasicBlock::iterator II, 360283625Sdim unsigned FrameRegIdx, 361283625Sdim unsigned FrameReg, int &Offset, 362283625Sdim const ARMBaseInstrInfo &TII) const { 363283625Sdim MachineInstr &MI = *II; 364283625Sdim MachineBasicBlock &MBB = *MI.getParent(); 365283625Sdim assert(MBB.getParent()->getSubtarget<ARMSubtarget>().isThumb1Only() && 366283625Sdim "This isn't needed for thumb2!"); 367283625Sdim DebugLoc dl = MI.getDebugLoc(); 368283625Sdim MachineInstrBuilder MIB(*MBB.getParent(), &MI); 369283625Sdim unsigned Opcode = MI.getOpcode(); 370283625Sdim const MCInstrDesc &Desc = MI.getDesc(); 371283625Sdim unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); 372283625Sdim 373283625Sdim if (Opcode == ARM::tADDframe) { 374283625Sdim Offset += MI.getOperand(FrameRegIdx+1).getImm(); 375360784Sdim Register DestReg = MI.getOperand(0).getReg(); 376283625Sdim 377283625Sdim emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII, 378283625Sdim *this); 379283625Sdim MBB.erase(II); 380283625Sdim return true; 381283625Sdim } else { 382283625Sdim if (AddrMode != ARMII::AddrModeT1_s) 383283625Sdim llvm_unreachable("Unsupported addressing mode!"); 384283625Sdim 385283625Sdim unsigned ImmIdx = FrameRegIdx + 1; 386283625Sdim int InstrOffs = MI.getOperand(ImmIdx).getImm(); 387283625Sdim unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5; 388283625Sdim unsigned Scale = 4; 389283625Sdim 390283625Sdim Offset += InstrOffs * Scale; 391283625Sdim assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!"); 392283625Sdim 393283625Sdim // Common case: small offset, fits into instruction. 394283625Sdim MachineOperand &ImmOp = MI.getOperand(ImmIdx); 395283625Sdim int ImmedOffset = Offset / Scale; 396283625Sdim unsigned Mask = (1 << NumBits) - 1; 397283625Sdim 398283625Sdim if ((unsigned)Offset <= Mask * Scale) { 399283625Sdim // Replace the FrameIndex with the frame register (e.g., sp). 400283625Sdim MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 401283625Sdim ImmOp.ChangeToImmediate(ImmedOffset); 402283625Sdim 403283625Sdim // If we're using a register where sp was stored, convert the instruction 404283625Sdim // to the non-SP version. 405283625Sdim unsigned NewOpc = convertToNonSPOpcode(Opcode); 406283625Sdim if (NewOpc != Opcode && FrameReg != ARM::SP) 407283625Sdim MI.setDesc(TII.get(NewOpc)); 408283625Sdim 409283625Sdim return true; 410283625Sdim } 411283625Sdim 412283625Sdim NumBits = 5; 413283625Sdim Mask = (1 << NumBits) - 1; 414283625Sdim 415283625Sdim // If this is a thumb spill / restore, we will be using a constpool load to 416283625Sdim // materialize the offset. 417283625Sdim if (Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) { 418283625Sdim ImmOp.ChangeToImmediate(0); 419283625Sdim } else { 420283625Sdim // Otherwise, it didn't fit. Pull in what we can to simplify the immed. 421283625Sdim ImmedOffset = ImmedOffset & Mask; 422283625Sdim ImmOp.ChangeToImmediate(ImmedOffset); 423283625Sdim Offset &= ~(Mask * Scale); 424283625Sdim } 425283625Sdim } 426283625Sdim 427283625Sdim return Offset == 0; 428283625Sdim} 429283625Sdim 430283625Sdimvoid ThumbRegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg, 431283625Sdim int64_t Offset) const { 432283625Sdim const MachineFunction &MF = *MI.getParent()->getParent(); 433283625Sdim const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>(); 434283625Sdim if (!STI.isThumb1Only()) 435283625Sdim return ARMBaseRegisterInfo::resolveFrameIndex(MI, BaseReg, Offset); 436283625Sdim 437283625Sdim const ARMBaseInstrInfo &TII = *STI.getInstrInfo(); 438283625Sdim int Off = Offset; // ARM doesn't need the general 64-bit offsets 439283625Sdim unsigned i = 0; 440283625Sdim 441283625Sdim while (!MI.getOperand(i).isFI()) { 442283625Sdim ++i; 443283625Sdim assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 444283625Sdim } 445283625Sdim bool Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII); 446283625Sdim assert (Done && "Unable to resolve frame index!"); 447283625Sdim (void)Done; 448283625Sdim} 449283625Sdim 450283625Sdimvoid ThumbRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 451283625Sdim int SPAdj, unsigned FIOperandNum, 452283625Sdim RegScavenger *RS) const { 453283625Sdim MachineInstr &MI = *II; 454283625Sdim MachineBasicBlock &MBB = *MI.getParent(); 455283625Sdim MachineFunction &MF = *MBB.getParent(); 456283625Sdim const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>(); 457283625Sdim if (!STI.isThumb1Only()) 458283625Sdim return ARMBaseRegisterInfo::eliminateFrameIndex(II, SPAdj, FIOperandNum, 459283625Sdim RS); 460283625Sdim 461283625Sdim unsigned VReg = 0; 462283625Sdim const ARMBaseInstrInfo &TII = *STI.getInstrInfo(); 463283625Sdim DebugLoc dl = MI.getDebugLoc(); 464283625Sdim MachineInstrBuilder MIB(*MBB.getParent(), &MI); 465283625Sdim 466341825Sdim unsigned FrameReg; 467283625Sdim int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 468341825Sdim const ARMFrameLowering *TFI = getFrameLowering(MF); 469341825Sdim int Offset = TFI->ResolveFrameIndexReference(MF, FrameIndex, FrameReg, SPAdj); 470283625Sdim 471283625Sdim // PEI::scavengeFrameVirtualRegs() cannot accurately track SPAdj because the 472283625Sdim // call frame setup/destroy instructions have already been eliminated. That 473283625Sdim // means the stack pointer cannot be used to access the emergency spill slot 474283625Sdim // when !hasReservedCallFrame(). 475283625Sdim#ifndef NDEBUG 476283625Sdim if (RS && FrameReg == ARM::SP && RS->isScavengingFrameIndex(FrameIndex)){ 477283625Sdim assert(STI.getFrameLowering()->hasReservedCallFrame(MF) && 478283625Sdim "Cannot use SP to access the emergency spill slot in " 479283625Sdim "functions without a reserved call frame"); 480314564Sdim assert(!MF.getFrameInfo().hasVarSizedObjects() && 481283625Sdim "Cannot use SP to access the emergency spill slot in " 482283625Sdim "functions with variable sized frame objects"); 483283625Sdim } 484283625Sdim#endif // NDEBUG 485283625Sdim 486283625Sdim // Special handling of dbg_value instructions. 487283625Sdim if (MI.isDebugValue()) { 488283625Sdim MI.getOperand(FIOperandNum). ChangeToRegister(FrameReg, false /*isDef*/); 489283625Sdim MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset); 490283625Sdim return; 491283625Sdim } 492283625Sdim 493283625Sdim // Modify MI as necessary to handle as much of 'Offset' as possible 494341825Sdim assert(MF.getInfo<ARMFunctionInfo>()->isThumbFunction() && 495283625Sdim "This eliminateFrameIndex only supports Thumb1!"); 496283625Sdim if (rewriteFrameIndex(MI, FIOperandNum, FrameReg, Offset, TII)) 497283625Sdim return; 498283625Sdim 499283625Sdim // If we get here, the immediate doesn't fit into the instruction. We folded 500283625Sdim // as much as possible above, handle the rest, providing a register that is 501283625Sdim // SP+LargeImm. 502283625Sdim assert(Offset && "This code isn't needed if offset already handled!"); 503283625Sdim 504283625Sdim unsigned Opcode = MI.getOpcode(); 505283625Sdim 506283625Sdim // Remove predicate first. 507283625Sdim int PIdx = MI.findFirstPredOperandIdx(); 508283625Sdim if (PIdx != -1) 509283625Sdim removeOperands(MI, PIdx); 510283625Sdim 511283625Sdim if (MI.mayLoad()) { 512283625Sdim // Use the destination register to materialize sp + offset. 513360784Sdim Register TmpReg = MI.getOperand(0).getReg(); 514283625Sdim bool UseRR = false; 515283625Sdim if (Opcode == ARM::tLDRspi) { 516314564Sdim if (FrameReg == ARM::SP || STI.genExecuteOnly()) 517283625Sdim emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg, 518283625Sdim Offset, false, TII, *this); 519283625Sdim else { 520283625Sdim emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset); 521283625Sdim UseRR = true; 522283625Sdim } 523283625Sdim } else { 524283625Sdim emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII, 525283625Sdim *this); 526283625Sdim } 527283625Sdim 528283625Sdim MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi)); 529283625Sdim MI.getOperand(FIOperandNum).ChangeToRegister(TmpReg, false, false, true); 530283625Sdim if (UseRR) 531283625Sdim // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame 532283625Sdim // register. The offset is already handled in the vreg value. 533283625Sdim MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false, 534283625Sdim false); 535283625Sdim } else if (MI.mayStore()) { 536283625Sdim VReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass); 537283625Sdim bool UseRR = false; 538283625Sdim 539283625Sdim if (Opcode == ARM::tSTRspi) { 540314564Sdim if (FrameReg == ARM::SP || STI.genExecuteOnly()) 541283625Sdim emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg, 542283625Sdim Offset, false, TII, *this); 543283625Sdim else { 544283625Sdim emitLoadConstPool(MBB, II, dl, VReg, 0, Offset); 545283625Sdim UseRR = true; 546283625Sdim } 547283625Sdim } else 548283625Sdim emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII, 549283625Sdim *this); 550283625Sdim MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi)); 551283625Sdim MI.getOperand(FIOperandNum).ChangeToRegister(VReg, false, false, true); 552283625Sdim if (UseRR) 553283625Sdim // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame 554283625Sdim // register. The offset is already handled in the vreg value. 555283625Sdim MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false, 556283625Sdim false); 557283625Sdim } else { 558283625Sdim llvm_unreachable("Unexpected opcode!"); 559283625Sdim } 560283625Sdim 561283625Sdim // Add predicate back if it's needed. 562283625Sdim if (MI.isPredicable()) 563321369Sdim MIB.add(predOps(ARMCC::AL)); 564283625Sdim} 565353358Sdim 566353358Sdimbool 567353358SdimThumbRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const { 568353358Sdim if (MF.getSubtarget<ARMSubtarget>().isThumb1Only()) { 569353358Sdim // For Thumb1, the emergency spill slot must be some small positive 570353358Sdim // offset from the base/stack pointer. 571353358Sdim return false; 572353358Sdim } 573353358Sdim // For Thumb2, put the emergency spill slot next to FP. 574353358Sdim return true; 575353358Sdim} 576