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