Thumb1RegisterInfo.cpp revision fa226bccaa90c520cac154df74069bbabb976eab
131c24bf5b39cc8391d4cfdbf8cf5163975fdb81eJim Grosbach//===- Thumb1RegisterInfo.cpp - Thumb-1 Register Information ----*- C++ -*-===// 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 15a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARM.h" 16a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMAddressingModes.h" 1777521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin#include "ARMBaseInstrInfo.h" 18a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMMachineFunctionInfo.h" 19a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMSubtarget.h" 20b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin#include "Thumb1InstrInfo.h" 21b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin#include "Thumb1RegisterInfo.h" 22a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/Constants.h" 23a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/DerivedTypes.h" 249adc0abad3c3ed40a268ccbcee0c74cb9e1359feOwen Anderson#include "llvm/Function.h" 259adc0abad3c3ed40a268ccbcee0c74cb9e1359feOwen Anderson#include "llvm/LLVMContext.h" 26a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineConstantPool.h" 27a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineFrameInfo.h" 28a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineFunction.h" 29a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineInstrBuilder.h" 30a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineLocation.h" 31a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineRegisterInfo.h" 3216c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov#include "llvm/Target/TargetFrameLowering.h" 33a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/Target/TargetMachine.h" 344e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach#include "llvm/Support/CommandLine.h" 35ab7c09b6b6f4516a631fd6788918c237c83939afTorok Edwin#include "llvm/Support/ErrorHandling.h" 36dac237e18209b697a8ba122d0ddd9cad4dfba1f8Torok Edwin#include "llvm/Support/raw_ostream.h" 37a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 388c407d45964fbba19719be555324f247e4fb14e1Dan Gohmannamespace llvm { 394e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbachextern cl::opt<bool> ReuseFrameIndexVals; 408c407d45964fbba19719be555324f247e4fb14e1Dan Gohman} 418c407d45964fbba19719be555324f247e4fb14e1Dan Gohman 428c407d45964fbba19719be555324f247e4fb14e1Dan Gohmanusing namespace llvm; 434e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach 44db5a71a8e01ed9a0d93a19176df6ea0aea510d7bDavid GoodwinThumb1RegisterInfo::Thumb1RegisterInfo(const ARMBaseInstrInfo &tii, 45b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const ARMSubtarget &sti) 46a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov : ARMBaseRegisterInfo(tii, sti) { 47a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 48a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 49c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesenconst TargetRegisterClass* 50c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund OlesenThumb1RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) 51c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen const { 52fa226bccaa90c520cac154df74069bbabb976eabJakob Stoklund Olesen if (ARM::tGPRRegClass.hasSubClassEq(RC)) 53c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen return ARM::tGPRRegisterClass; 54c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC); 55c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen} 56c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen 571db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesenconst TargetRegisterClass * 581db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund OlesenThumb1RegisterInfo::getPointerRegClass(unsigned Kind) const { 591db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesen return ARM::tGPRRegisterClass; 601db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesen} 611db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesen 62a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitLoadConstPool - Emits a load from constpool to materialize the 63a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// specified immediate. 643daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikovvoid 653daccd82d3151fa3629de430b55698a81084fc9eAnton KorobeynikovThumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, 663daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 673daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov DebugLoc dl, 683daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov unsigned DestReg, unsigned SubIdx, 693daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov int Val, 703daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov ARMCC::CondCodes Pred, unsigned PredReg, 713daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov unsigned MIFlags) const { 72a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFunction &MF = *MBB.getParent(); 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!"); 11365c58daa8b8985d2116216043103009815a55e77Jim Grosbach LdReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass); 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; 185446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng bool NeedPred = false; 186a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 187a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == BaseReg && BaseReg == ARM::SP) { 188a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); 189a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 7; 190a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 191a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; 192a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isTwoAddr = true; 193a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else if (!isSub && BaseReg == ARM::SP) { 194a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add sp, 403 195a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // => 196a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add sp, 100 * 4 197a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add r1, 3 198a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!isMul4) { 199a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes &= ~3; 200a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ExtraOpc = ARM::tADDi3; 201a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 202a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 203a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 204a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = ARM::tADDrSPi; 205a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 206a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // sp = sub sp, c 207a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = sub sp, c 208a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r8 = sub sp, c 209a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg != BaseReg) 210a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DstNotEqBase = true; 211a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 212f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng if (DestReg == ARM::SP) { 213f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; 214f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); 215f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng NumBits = 7; 216f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Scale = 4; 217f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng } else { 218f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; 219f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng NumBits = 8; 220f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng NeedPred = NeedCC = true; 221f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng } 222a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isTwoAddr = true; 223a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 224a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 225a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale); 226a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2; 227a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumMIs > Threshold) { 228a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // This will expand into too many instructions. Load the immediate from a 229a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // constpool entry. 2303daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, MBBI, dl, 2313daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov DestReg, BaseReg, NumBytes, true, 2323daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov TII, MRI, MIFlags); 233a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return; 234a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 235a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 236a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DstNotEqBase) { 23755ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov if (isARMLowRegister(DestReg) && isARMLowRegister(BaseReg)) { 238a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If both are low registers, emit DestReg = add BaseReg, max(Imm, 7) 239a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = (1 << 3) - 1; 240a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 241a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 242446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng const TargetInstrDesc &TID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); 243446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng const MachineInstrBuilder MIB = 2443daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg).setMIFlags(MIFlags)); 245446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal)); 246a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 247a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) 2483daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .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); 265446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedPred) 266446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MIB = AddDefaultPred(MIB); 2673daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov MIB.setMIFlags(MIFlags); 268446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 269a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 270a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isKill = BaseReg != ARM::SP; 271446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); 272446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedCC) 273b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng MIB = AddDefaultT1CC(MIB); 274446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal); 275446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedPred) 276446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MIB = AddDefaultPred(MIB); 2773daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov MIB.setMIFlags(MIFlags); 278a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 2793daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov BaseReg = DestReg; 280a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::tADDrSPi) { 281a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r4 = add sp, imm 282a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r4 = add r4, imm 283a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ... 284a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 285a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 1; 286a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Chunk = ((1 << NumBits) - 1) * Scale; 287a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; 288446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng NeedPred = NeedCC = isTwoAddr = true; 289a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 290a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 291a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 292a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 293446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (ExtraOpc) { 294446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng const TargetInstrDesc &TID = TII.get(ExtraOpc); 295b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)) 296446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addReg(DestReg, RegState::Kill) 2973daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .addImm(((unsigned)NumBytes) & 3) 2983daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .setMIFlags(MIFlags)); 299446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 300a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 301a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 30255ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikovstatic void emitSPUpdate(MachineBasicBlock &MBB, 30355ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov MachineBasicBlock::iterator &MBBI, 30455ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov const TargetInstrInfo &TII, DebugLoc dl, 305b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo &MRI, 30655ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov int NumBytes) { 30757caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, TII, 30857caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov MRI); 309a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 310a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 311b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo:: 312a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton KorobeynikoveliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 313a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator I) const { 31416c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 315d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov 316d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov if (!TFI->hasReservedCallFrame(MF)) { 317a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If we have alloca, convert as follows: 318a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ADJCALLSTACKDOWN -> sub, sp, sp, amount 319a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ADJCALLSTACKUP -> add, sp, sp, amount 320a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineInstr *Old = I; 321a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = Old->getDebugLoc(); 322a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Amount = Old->getOperand(0).getImm(); 323a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Amount != 0) { 324a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // We need to keep the stack aligned properly. To do this, we round the 325a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // amount of space needed for the outgoing arguments up to the next 326a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // alignment boundary. 32716c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov unsigned Align = TFI->getStackAlignment(); 328a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Amount = (Amount+Align-1)/Align*Align; 329a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 330a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Replace the pseudo instruction with a new instruction... 331a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Opc = Old->getOpcode(); 332a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) { 33355ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, I, TII, dl, *this, -Amount); 334a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 335a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP); 33655ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, I, TII, dl, *this, Amount); 337a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 338a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 339a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 340a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBB.erase(I); 341a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 342a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 343a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbConstant - Emit a series of instructions to materialize a 344a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constant. 345a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic void emitThumbConstant(MachineBasicBlock &MBB, 346a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 347a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg, int Imm, 348a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrInfo &TII, 349b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo& MRI, 350a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl) { 351a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = Imm < 0; 352a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (isSub) Imm = -Imm; 353a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 354a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Chunk = (1 << 8) - 1; 355a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ThisVal = (Imm > Chunk) ? Chunk : Imm; 356a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Imm -= ThisVal; 357b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), 358b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng DestReg)) 359446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addImm(ThisVal)); 360a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Imm > 0) 36157caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, dl, DestReg, DestReg, Imm, TII, MRI); 362446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (isSub) { 363446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng const TargetInstrDesc &TID = TII.get(ARM::tRSB); 364b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)) 365446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addReg(DestReg, RegState::Kill)); 366446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 367446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng} 368446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 369446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Chengstatic void removeOperands(MachineInstr &MI, unsigned i) { 370446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng unsigned Op = i; 371446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng for (unsigned e = MI.getNumOperands(); i != e; ++i) 372446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MI.RemoveOperand(Op); 373a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 374a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 3757a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling/// convertToNonSPOpcode - Change the opcode to the non-SP version, because 3767a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling/// we're replacing the frame index with a non-SP register. 3777a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendlingstatic unsigned convertToNonSPOpcode(unsigned Opcode) { 3787a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling switch (Opcode) { 3797a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling case ARM::tLDRspi: 3805a54516adf2b15fa337445d327ec3ad9bd1e3648Bill Wendling case ARM::tRestore: // FIXME: Should this opcode be here? 3817a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling return ARM::tLDRi; 3827a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 3837a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling case ARM::tSTRspi: 3845a54516adf2b15fa337445d327ec3ad9bd1e3648Bill Wendling case ARM::tSpill: // FIXME: Should this opcode be here? 3857a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling return ARM::tSTRi; 3867a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling } 3877a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 3887a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling return Opcode; 3897a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling} 3907a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 39174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool Thumb1RegisterInfo:: 39274d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachrewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, 39374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned FrameReg, int &Offset, 39474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const ARMBaseInstrInfo &TII) const { 395a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineInstr &MI = *II; 396a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock &MBB = *MI.getParent(); 397a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = MI.getDebugLoc(); 398a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Opcode = MI.getOpcode(); 399a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrDesc &Desc = MI.getDesc(); 400a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); 401a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 402a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opcode == ARM::tADDrSPi) { 40374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach Offset += MI.getOperand(FrameRegIdx+1).getImm(); 404a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 405a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Can't use tADDrSPi if it's based off the frame pointer. 406a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits = 0; 407a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Scale = 1; 408a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (FrameReg != ARM::SP) { 409a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opcode = ARM::tADDi3; 410446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MI.setDesc(TII.get(Opcode)); 411a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 3; 412a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 413a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 414a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 415a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert((Offset & 3) == 0 && 416a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov "Thumb add/sub sp, #imm immediate must be multiple of 4!"); 417a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 418a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 41935f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen unsigned PredReg; 42035f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) { 421a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Turn it into a move. 422d83360694a6d82772cf31a0be8a64570c2e5cb88Evan Cheng MI.setDesc(TII.get(ARM::tMOVgpr2tgpr)); 42374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 42435f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen // Remove offset and remaining explicit predicate operands. 42574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach do MI.RemoveOperand(FrameRegIdx+1); 42674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach while (MI.getNumOperands() > FrameRegIdx+1 && 42774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach (!MI.getOperand(FrameRegIdx+1).isReg() || 42874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach !MI.getOperand(FrameRegIdx+1).isImm())); 42974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 430a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 431a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 432a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Common case: small offset, fits into instruction. 433a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Mask = (1 << NumBits) - 1; 434a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (((Offset / Scale) & ~Mask) == 0) { 435a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Replace the FrameIndex with sp / fp 436446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (Opcode == ARM::tADDi3) { 43774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach removeOperands(MI, FrameRegIdx); 438446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB(&MI); 439b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg) 440f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng .addImm(Offset / Scale)); 441446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 44274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 44374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset / Scale); 444446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 44574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 446a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 447a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 448a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg = MI.getOperand(0).getReg(); 449a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Bytes = (Offset > 0) ? Offset : -Offset; 450a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = calcNumMI(Opcode, 0, Bytes, NumBits, Scale); 451a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // MI would expand into a large number of instructions. Don't try to 452a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // simplify the immediate. 453a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumMIs > 2) { 45457caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII, 45557caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov *this); 456a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBB.erase(II); 45774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 458a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 459a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 460a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Offset > 0) { 461a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Translate r0 = add sp, imm to 462a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add sp, 255*4 463a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add r0, (imm - 255*4) 464446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (Opcode == ARM::tADDi3) { 46574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach removeOperands(MI, FrameRegIdx); 466446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB(&MI); 467b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg).addImm(Mask)); 468446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 46974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 47074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Mask); 471446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 472a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset = (Offset - Mask * Scale); 4737896c9f436a4eda5ec15e882a7505ba482a2fcd0Chris Lattner MachineBasicBlock::iterator NII = llvm::next(II); 47457caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, NII, dl, DestReg, DestReg, Offset, TII, 47557caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov *this); 476a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 477a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Translate r0 = add sp, -imm to 478a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = -imm (this is then translated into a series of instructons) 479a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add r0, sp 480a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbConstant(MBB, II, DestReg, Offset, TII, *this, dl); 481bae20a6353583089224b94280a2dd69805dca247Evan Cheng 482a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.setDesc(TII.get(ARM::tADDhirr)); 48374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false, false, true); 48474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx+1).ChangeToRegister(FrameReg, false); 485bae20a6353583089224b94280a2dd69805dca247Evan Cheng if (Opcode == ARM::tADDi3) { 486bae20a6353583089224b94280a2dd69805dca247Evan Cheng MachineInstrBuilder MIB(&MI); 487bae20a6353583089224b94280a2dd69805dca247Evan Cheng AddDefaultPred(MIB); 488bae20a6353583089224b94280a2dd69805dca247Evan Cheng } 489a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 49074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 491a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 4927a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling if (AddrMode != ARMII::AddrModeT1_s) 493c23197a26f34f559ea9797de51e187087c039c42Torok Edwin llvm_unreachable("Unsupported addressing mode!"); 4947a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 4957a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling unsigned ImmIdx = FrameRegIdx + 1; 4967a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling int InstrOffs = MI.getOperand(ImmIdx).getImm(); 4977a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5; 4987a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling unsigned Scale = 4; 499a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 500a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset += InstrOffs * Scale; 5017a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!"); 502a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 503a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Common case: small offset, fits into instruction. 504a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineOperand &ImmOp = MI.getOperand(ImmIdx); 505a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ImmedOffset = Offset / Scale; 506a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Mask = (1 << NumBits) - 1; 5077a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 508a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if ((unsigned)Offset <= Mask * Scale) { 5097a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling // Replace the FrameIndex with the frame register (e.g., sp). 51074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 511a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(ImmedOffset); 5127a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 5137a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling // If we're using a register where sp was stored, convert the instruction 5147a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling // to the non-SP version. 5157a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling unsigned NewOpc = convertToNonSPOpcode(Opcode); 5167a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling if (NewOpc != Opcode && FrameReg != ARM::SP) 5177a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling MI.setDesc(TII.get(NewOpc)); 5187a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 51974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 520a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 521a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 5227a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling NumBits = 5; 5237a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling Mask = (1 << NumBits) - 1; 5247a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 525a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If this is a thumb spill / restore, we will be using a constpool load to 526a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // materialize the offset. 5277a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling if (Opcode == ARM::tRestore || Opcode == ARM::tSpill) { 528a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(0); 5297a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling } else { 530a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Otherwise, it didn't fit. Pull in what we can to simplify the immed. 531a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmedOffset = ImmedOffset & Mask; 532a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(ImmedOffset); 5337a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling Offset &= ~(Mask * Scale); 534a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 535a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 5367a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 53774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return Offset == 0; 53874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach} 53974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 54074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachvoid 54174d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I, 54274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned BaseReg, int64_t Offset) const { 54374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineInstr &MI = *I; 54474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach int Off = Offset; // ARM doesn't need the general 64-bit offsets 54574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned i = 0; 54674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 54774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach while (!MI.getOperand(i).isFI()) { 54874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach ++i; 54974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 55074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 55174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach bool Done = false; 55274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII); 55374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert (Done && "Unable to resolve frame index!"); 55474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach} 55574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 55674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// saveScavengerRegister - Spill the register so it can be used by the 55774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// register scavenger. Return true. 55874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool 55974d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, 56074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineBasicBlock::iterator I, 56174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineBasicBlock::iterator &UseMI, 56274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const TargetRegisterClass *RC, 56374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned Reg) const { 56474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Thumb1 can't use the emergency spill slot on the stack because 56574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // ldr/str immediate offsets must be positive, and if we're referencing 56674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // off the frame pointer (if, for example, there are alloca() calls in 56774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // the function, the offset will be negative. Use R12 instead since that's 56874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // a call clobbered register that we know won't be used in Thumb1 mode. 56974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach DebugLoc DL; 57074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach BuildMI(MBB, I, DL, TII.get(ARM::tMOVtgpr2gpr)). 57174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach addReg(ARM::R12, RegState::Define).addReg(Reg, RegState::Kill); 57274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 57374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // The UseMI is where we would like to restore the register. If there's 57474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // interference with R12 before then, however, we'll need to restore it 57574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // before that instead and adjust the UseMI. 57674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach bool done = false; 57774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) { 57874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (II->isDebugValue()) 57974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach continue; 58074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // If this instruction affects R12, adjust our restore point. 58174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) { 58274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const MachineOperand &MO = II->getOperand(i); 58374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (!MO.isReg() || MO.isUndef() || !MO.getReg() || 58474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach TargetRegisterInfo::isVirtualRegister(MO.getReg())) 58574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach continue; 58674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (MO.getReg() == ARM::R12) { 58774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach UseMI = II; 58874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach done = true; 58974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach break; 59074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 59174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 59274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 59374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Restore the register from R12 59474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVgpr2tgpr)). 59574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill); 59674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 59774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 59874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach} 59974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 600fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbachvoid 60174d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 602fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach int SPAdj, RegScavenger *RS) const { 60374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned VReg = 0; 60474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned i = 0; 60574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineInstr &MI = *II; 60674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineBasicBlock &MBB = *MI.getParent(); 60774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineFunction &MF = *MBB.getParent(); 60874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 60974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach DebugLoc dl = MI.getDebugLoc(); 61074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 61174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach while (!MI.getOperand(i).isFI()) { 61274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach ++i; 61374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 61474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 61574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 61674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned FrameReg = ARM::SP; 61774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach int FrameIndex = MI.getOperand(i).getIndex(); 61874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + 61974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MF.getFrameInfo()->getStackSize() + SPAdj; 62074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 621ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach if (AFI->isGPRCalleeSavedArea1Frame(FrameIndex)) 622ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach Offset -= AFI->getGPRCalleeSavedArea1Offset(); 623ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach else if (AFI->isGPRCalleeSavedArea2Frame(FrameIndex)) 624ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach Offset -= AFI->getGPRCalleeSavedArea2Offset(); 62574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach else if (MF.getFrameInfo()->hasVarSizedObjects()) { 62616c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov assert(SPAdj == 0 && MF.getTarget().getFrameLowering()->hasFP(MF) && 6277920d96964d707a3af85332c98d95b2fabc3d5c9Benjamin Kramer "Unexpected"); 62874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // There are alloca()'s in this function, must reference off the frame 62965482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach // pointer or base pointer instead. 63065482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach if (!hasBasePointer(MF)) { 63165482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach FrameReg = getFrameRegister(MF); 63265482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach Offset -= AFI->getFramePtrSpillOffset(); 63365482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach } else 63465482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach FrameReg = BasePtr; 63574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 63674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 63774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Special handling of dbg_value instructions. 63874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (MI.isDebugValue()) { 63974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(i). ChangeToRegister(FrameReg, false /*isDef*/); 64074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(i+1).ChangeToImmediate(Offset); 641fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach return; 64274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 64374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 64474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Modify MI as necessary to handle as much of 'Offset' as possible 64574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert(AFI->isThumbFunction() && 64674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach "This eliminateFrameIndex only supports Thumb1!"); 64774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (rewriteFrameIndex(MI, i, FrameReg, Offset, TII)) 648fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach return; 649a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 650a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If we get here, the immediate doesn't fit into the instruction. We folded 651a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // as much as possible above, handle the rest, providing a register that is 652a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // SP+LargeImm. 653a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(Offset && "This code isn't needed if offset already handled!"); 654a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 65574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned Opcode = MI.getOpcode(); 65674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const TargetInstrDesc &Desc = MI.getDesc(); 65774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 658446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng // Remove predicate first. 659446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng int PIdx = MI.findFirstPredOperandIdx(); 660446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (PIdx != -1) 661446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng removeOperands(MI, PIdx); 662446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 663a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Desc.mayLoad()) { 664a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Use the destination register to materialize sp + offset. 665a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned TmpReg = MI.getOperand(0).getReg(); 666a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool UseRR = false; 667a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opcode == ARM::tRestore) { 668a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (FrameReg == ARM::SP) 6693daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg, 6703daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov Offset, false, TII, *this); 671a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 672378445303b10b092a898a75131141a8259cff50bEvan Cheng emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset); 673a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov UseRR = true; 674a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 675446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 67657caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII, 67757caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov *this); 678446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 679446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 6806e90ce21cc2b0627ee9219e3fb0cf808f2b73328Eric Christopher MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi)); 681a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(TmpReg, false, false, true); 682a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (UseRR) 6835f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame 6845f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach // register. The offset is already handled in the vreg value. 6855f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach MI.getOperand(i+1).ChangeToRegister(FrameReg, false, false, false); 686a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else if (Desc.mayStore()) { 687b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach VReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass); 6883d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach bool UseRR = false; 689b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach 6903d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach if (Opcode == ARM::tSpill) { 6913d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach if (FrameReg == ARM::SP) 6923daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg, 6933daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov Offset, false, TII, *this); 6943d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach else { 695b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach emitLoadConstPool(MBB, II, dl, VReg, 0, Offset); 6963d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach UseRR = true; 6973d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach } 6983d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach } else 69957caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII, 70057caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov *this); 7016e90ce21cc2b0627ee9219e3fb0cf808f2b73328Eric Christopher MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi)); 702b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach MI.getOperand(i).ChangeToRegister(VReg, false, false, true); 7035f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach if (UseRR) 7045f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame 7055f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach // register. The offset is already handled in the vreg value. 7065f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach MI.getOperand(i+1).ChangeToRegister(FrameReg, false, false, false); 707f4caf69720d807573c50d41aa06bcec1c99bdbbdBill Wendling } else { 708a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(false && "Unexpected opcode!"); 709f4caf69720d807573c50d41aa06bcec1c99bdbbdBill Wendling } 710446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 711446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng // Add predicate back if it's needed. 712446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (MI.getDesc().isPredicable()) { 713446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB(&MI); 714446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng AddDefaultPred(MIB); 715446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 716a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 717