Thumb1RegisterInfo.cpp revision 65482b1bb873dd820f54a24a2f34bd65f2669e5c
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" 32a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/Target/TargetFrameInfo.h" 33a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/Target/TargetMachine.h" 34a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/ADT/BitVector.h" 35a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/ADT/SmallVector.h" 364e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach#include "llvm/Support/CommandLine.h" 37ab7c09b6b6f4516a631fd6788918c237c83939afTorok Edwin#include "llvm/Support/ErrorHandling.h" 38dac237e18209b697a8ba122d0ddd9cad4dfba1f8Torok Edwin#include "llvm/Support/raw_ostream.h" 39a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 408c407d45964fbba19719be555324f247e4fb14e1Dan Gohmannamespace llvm { 414e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbachextern cl::opt<bool> ReuseFrameIndexVals; 428c407d45964fbba19719be555324f247e4fb14e1Dan Gohman} 438c407d45964fbba19719be555324f247e4fb14e1Dan Gohman 448c407d45964fbba19719be555324f247e4fb14e1Dan Gohmanusing namespace llvm; 454e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach 46db5a71a8e01ed9a0d93a19176df6ea0aea510d7bDavid GoodwinThumb1RegisterInfo::Thumb1RegisterInfo(const ARMBaseInstrInfo &tii, 47b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const ARMSubtarget &sti) 48a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov : ARMBaseRegisterInfo(tii, sti) { 49a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 50a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 51a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitLoadConstPool - Emits a load from constpool to materialize the 52a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// specified immediate. 53b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, 54b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin MachineBasicBlock::iterator &MBBI, 5577521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin DebugLoc dl, 56378445303b10b092a898a75131141a8259cff50bEvan Cheng unsigned DestReg, unsigned SubIdx, 57378445303b10b092a898a75131141a8259cff50bEvan Cheng int Val, 58db5a71a8e01ed9a0d93a19176df6ea0aea510d7bDavid Goodwin ARMCC::CondCodes Pred, 59db5a71a8e01ed9a0d93a19176df6ea0aea510d7bDavid Goodwin unsigned PredReg) const { 60a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFunction &MF = *MBB.getParent(); 61a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineConstantPool *ConstantPool = MF.getConstantPool(); 6246510a73e977273ec67747eb34cbdb43f815e451Dan Gohman const Constant *C = ConstantInt::get( 631d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val); 64a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); 65a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 66378445303b10b092a898a75131141a8259cff50bEvan Cheng BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRcp)) 67378445303b10b092a898a75131141a8259cff50bEvan Cheng .addReg(DestReg, getDefRegState(true), SubIdx) 68378445303b10b092a898a75131141a8259cff50bEvan Cheng .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg); 69a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 70a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 7172852a8cfb605056d87b644d2e36b1346051413dEric Christopherbool Thumb1RegisterInfo::hasReservedCallFrame(const MachineFunction &MF) const { 72a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const MachineFrameInfo *FFI = MF.getFrameInfo(); 73a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned CFSize = FFI->getMaxCallFrameSize(); 74a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // It's not always a good idea to include the call frame as part of the 75a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // stack frame. ARM (especially Thumb) has small immediate offset to 76a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // address the stack frame. So a large call frame can cause poor codegen 77a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // and may even makes it impossible to scavenge a register. 78a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (CFSize >= ((1 << 8) - 1) * 4 / 2) // Half of imm8 * 4 79a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return false; 80a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 81a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return !MF.getFrameInfo()->hasVarSizedObjects(); 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, 92a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg, unsigned BaseReg, 93a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int NumBytes, bool CanChangeCC, 94a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrInfo &TII, 95b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo& MRI, 96a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl) { 973d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach MachineFunction &MF = *MBB.getParent(); 9855ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov bool isHigh = !isARMLowRegister(DestReg) || 9955ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov (BaseReg != 0 && !isARMLowRegister(BaseReg)); 100a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = false; 101a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Subtract doesn't have high register version. Load the negative value 102a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // if either base or dest register is a high register. Also, if do not 103a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // issue sub as part of the sequence if condition register is to be 104a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // preserved. 105a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes < 0 && !isHigh && CanChangeCC) { 106a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isSub = true; 107a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = -NumBytes; 108a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 109a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned LdReg = DestReg; 110a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == ARM::SP) { 111a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(BaseReg == ARM::SP && "Unexpected!"); 11265c58daa8b8985d2116216043103009815a55e77Jim Grosbach LdReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass); 113a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 114a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 115a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes <= 255 && NumBytes >= 0) 116b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) 117446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addImm(NumBytes); 118a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else if (NumBytes < 0 && NumBytes >= -255) { 119b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) 120446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addImm(NumBytes); 121b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg)) 122a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(LdReg, RegState::Kill); 123a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else 124378445303b10b092a898a75131141a8259cff50bEvan Cheng MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes); 125a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 126a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Emit add / sub. 127a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr); 128446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB = 129446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); 130446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (Opc != ARM::tADDhirr) 131b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng MIB = AddDefaultT1CC(MIB); 132a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == ARM::SP || isSub) 133a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill); 134a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else 135a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill); 136446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng AddDefaultPred(MIB); 137a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 138a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 139a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// calcNumMI - Returns the number of instructions required to materialize 140a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// the specific add / sub r, c instruction. 141a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic unsigned calcNumMI(int Opc, int ExtraOpc, unsigned Bytes, 142a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits, unsigned Scale) { 143a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = 0; 144a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = ((1 << NumBits) - 1) * Scale; 145a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 146a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::tADDrSPi) { 147a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 148a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 149a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs++; 150a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 151a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 1; // Followed by a number of tADDi8. 152a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Chunk = ((1 << NumBits) - 1) * Scale; 153a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 154a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 155a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs += Bytes / Chunk; 156a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if ((Bytes % Chunk) != 0) 157a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs++; 158a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (ExtraOpc) 159a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs++; 160a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return NumMIs; 161a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 162a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 163a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize 164a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// a destreg = basereg + immediate in Thumb code. 165a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic 166a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovvoid emitThumbRegPlusImmediate(MachineBasicBlock &MBB, 167a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 168a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg, unsigned BaseReg, 169a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int NumBytes, const TargetInstrInfo &TII, 170b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo& MRI, 171a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl) { 172a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = NumBytes < 0; 173a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Bytes = (unsigned)NumBytes; 174a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (isSub) Bytes = -NumBytes; 175a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isMul4 = (Bytes & 3) == 0; 176a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isTwoAddr = false; 177a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool DstNotEqBase = false; 178a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits = 1; 179a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Scale = 1; 180a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Opc = 0; 181a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ExtraOpc = 0; 182446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng bool NeedCC = false; 183446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng bool NeedPred = false; 184a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 185a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == BaseReg && BaseReg == ARM::SP) { 186a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); 187a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 7; 188a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 189a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; 190a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isTwoAddr = true; 191a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else if (!isSub && BaseReg == ARM::SP) { 192a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add sp, 403 193a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // => 194a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add sp, 100 * 4 195a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add r1, 3 196a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!isMul4) { 197a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes &= ~3; 198a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ExtraOpc = ARM::tADDi3; 199a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 200a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 201a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 202a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = ARM::tADDrSPi; 203a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 204a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // sp = sub sp, c 205a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = sub sp, c 206a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r8 = sub sp, c 207a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg != BaseReg) 208a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DstNotEqBase = true; 209a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 210f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng if (DestReg == ARM::SP) { 211f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; 212f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); 213f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng NumBits = 7; 214f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Scale = 4; 215f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng } else { 216f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; 217f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng NumBits = 8; 218f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng NeedPred = NeedCC = true; 219f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng } 220a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isTwoAddr = true; 221a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 222a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 223a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale); 224a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2; 225a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumMIs > Threshold) { 226a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // This will expand into too many instructions. Load the immediate from a 227a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // constpool entry. 228a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, MBBI, DestReg, BaseReg, NumBytes, true, TII, 229a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MRI, dl); 230a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return; 231a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 232a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 233a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DstNotEqBase) { 23455ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov if (isARMLowRegister(DestReg) && isARMLowRegister(BaseReg)) { 235a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If both are low registers, emit DestReg = add BaseReg, max(Imm, 7) 236a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = (1 << 3) - 1; 237a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 238a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 239446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng const TargetInstrDesc &TID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); 240446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng const MachineInstrBuilder MIB = 241b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)); 242446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal)); 243a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 244a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) 245a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(BaseReg, RegState::Kill); 246a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 247a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BaseReg = DestReg; 248a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 249a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 250a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = ((1 << NumBits) - 1) * Scale; 251a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov while (Bytes) { 252a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 253a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 254a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ThisVal /= Scale; 255a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Build the new tADD / tSUB. 256446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (isTwoAddr) { 257446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); 258446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedCC) 259b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng MIB = AddDefaultT1CC(MIB); 260446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MIB .addReg(DestReg).addImm(ThisVal); 261446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedPred) 262446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MIB = AddDefaultPred(MIB); 263446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 264a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 265a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isKill = BaseReg != ARM::SP; 266446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); 267446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedCC) 268b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng MIB = AddDefaultT1CC(MIB); 269446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal); 270446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedPred) 271446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MIB = AddDefaultPred(MIB); 272a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BaseReg = DestReg; 273a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 274a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::tADDrSPi) { 275a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r4 = add sp, imm 276a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r4 = add r4, imm 277a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ... 278a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 279a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 1; 280a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Chunk = ((1 << NumBits) - 1) * Scale; 281a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; 282446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng NeedPred = NeedCC = isTwoAddr = true; 283a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 284a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 285a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 286a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 287446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (ExtraOpc) { 288446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng const TargetInstrDesc &TID = TII.get(ExtraOpc); 289b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)) 290446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addReg(DestReg, RegState::Kill) 291446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addImm(((unsigned)NumBytes) & 3)); 292446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 293a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 294a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 29555ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikovstatic void emitSPUpdate(MachineBasicBlock &MBB, 29655ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov MachineBasicBlock::iterator &MBBI, 29755ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov const TargetInstrInfo &TII, DebugLoc dl, 298b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo &MRI, 29955ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov int NumBytes) { 300a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, ARM::SP, NumBytes, TII, 30155ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov MRI, dl); 302a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 303a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 304b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo:: 305a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton KorobeynikoveliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 306a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator I) const { 307a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!hasReservedCallFrame(MF)) { 308a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If we have alloca, convert as follows: 309a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ADJCALLSTACKDOWN -> sub, sp, sp, amount 310a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ADJCALLSTACKUP -> add, sp, sp, amount 311a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineInstr *Old = I; 312a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = Old->getDebugLoc(); 313a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Amount = Old->getOperand(0).getImm(); 314a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Amount != 0) { 315a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // We need to keep the stack aligned properly. To do this, we round the 316a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // amount of space needed for the outgoing arguments up to the next 317a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // alignment boundary. 318a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); 319a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Amount = (Amount+Align-1)/Align*Align; 320a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 321a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Replace the pseudo instruction with a new instruction... 322a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Opc = Old->getOpcode(); 323a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) { 32455ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, I, TII, dl, *this, -Amount); 325a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 326a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP); 32755ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, I, TII, dl, *this, Amount); 328a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 329a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 330a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 331a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBB.erase(I); 332a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 333a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 334a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbConstant - Emit a series of instructions to materialize a 335a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constant. 336a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic void emitThumbConstant(MachineBasicBlock &MBB, 337a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 338a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg, int Imm, 339a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrInfo &TII, 340b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo& MRI, 341a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl) { 342a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = Imm < 0; 343a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (isSub) Imm = -Imm; 344a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 345a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Chunk = (1 << 8) - 1; 346a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ThisVal = (Imm > Chunk) ? Chunk : Imm; 347a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Imm -= ThisVal; 348b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), 349b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng DestReg)) 350446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addImm(ThisVal)); 351a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Imm > 0) 352a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, DestReg, DestReg, Imm, TII, MRI, dl); 353446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (isSub) { 354446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng const TargetInstrDesc &TID = TII.get(ARM::tRSB); 355b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)) 356446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addReg(DestReg, RegState::Kill)); 357446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 358446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng} 359446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 360446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Chengstatic void removeOperands(MachineInstr &MI, unsigned i) { 361446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng unsigned Op = i; 362446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng for (unsigned e = MI.getNumOperands(); i != e; ++i) 363446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MI.RemoveOperand(Op); 364a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 365a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 36674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool Thumb1RegisterInfo:: 36774d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachrewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, 36874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned FrameReg, int &Offset, 36974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const ARMBaseInstrInfo &TII) const { 370a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineInstr &MI = *II; 371a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock &MBB = *MI.getParent(); 372a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = MI.getDebugLoc(); 373a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Opcode = MI.getOpcode(); 374a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrDesc &Desc = MI.getDesc(); 375a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); 376a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 377a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opcode == ARM::tADDrSPi) { 37874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach Offset += MI.getOperand(FrameRegIdx+1).getImm(); 379a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 380a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Can't use tADDrSPi if it's based off the frame pointer. 381a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits = 0; 382a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Scale = 1; 383a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (FrameReg != ARM::SP) { 384a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opcode = ARM::tADDi3; 385446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MI.setDesc(TII.get(Opcode)); 386a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 3; 387a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 388a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 389a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 390a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert((Offset & 3) == 0 && 391a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov "Thumb add/sub sp, #imm immediate must be multiple of 4!"); 392a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 393a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 39435f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen unsigned PredReg; 39535f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) { 396a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Turn it into a move. 397d83360694a6d82772cf31a0be8a64570c2e5cb88Evan Cheng MI.setDesc(TII.get(ARM::tMOVgpr2tgpr)); 39874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 39935f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen // Remove offset and remaining explicit predicate operands. 40074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach do MI.RemoveOperand(FrameRegIdx+1); 40174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach while (MI.getNumOperands() > FrameRegIdx+1 && 40274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach (!MI.getOperand(FrameRegIdx+1).isReg() || 40374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach !MI.getOperand(FrameRegIdx+1).isImm())); 40474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 405a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 406a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 407a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Common case: small offset, fits into instruction. 408a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Mask = (1 << NumBits) - 1; 409a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (((Offset / Scale) & ~Mask) == 0) { 410a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Replace the FrameIndex with sp / fp 411446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (Opcode == ARM::tADDi3) { 41274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach removeOperands(MI, FrameRegIdx); 413446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB(&MI); 414b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg) 415f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng .addImm(Offset / Scale)); 416446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 41774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 41874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset / Scale); 419446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 42074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 421a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 422a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 423a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg = MI.getOperand(0).getReg(); 424a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Bytes = (Offset > 0) ? Offset : -Offset; 425a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = calcNumMI(Opcode, 0, Bytes, NumBits, Scale); 426a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // MI would expand into a large number of instructions. Don't try to 427a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // simplify the immediate. 428a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumMIs > 2) { 429a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, II, DestReg, FrameReg, Offset, TII, 430a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov *this, dl); 431a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBB.erase(II); 43274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 433a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 434a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 435a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Offset > 0) { 436a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Translate r0 = add sp, imm to 437a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add sp, 255*4 438a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add r0, (imm - 255*4) 439446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (Opcode == ARM::tADDi3) { 44074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach removeOperands(MI, FrameRegIdx); 441446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB(&MI); 442b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg).addImm(Mask)); 443446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 44474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 44574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Mask); 446446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 447a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset = (Offset - Mask * Scale); 4487896c9f436a4eda5ec15e882a7505ba482a2fcd0Chris Lattner MachineBasicBlock::iterator NII = llvm::next(II); 449a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, NII, DestReg, DestReg, Offset, TII, 450a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov *this, dl); 451a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 452a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Translate r0 = add sp, -imm to 453a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = -imm (this is then translated into a series of instructons) 454a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add r0, sp 455a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbConstant(MBB, II, DestReg, Offset, TII, *this, dl); 456bae20a6353583089224b94280a2dd69805dca247Evan Cheng 457a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.setDesc(TII.get(ARM::tADDhirr)); 45874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false, false, true); 45974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx+1).ChangeToRegister(FrameReg, false); 460bae20a6353583089224b94280a2dd69805dca247Evan Cheng if (Opcode == ARM::tADDi3) { 461bae20a6353583089224b94280a2dd69805dca247Evan Cheng MachineInstrBuilder MIB(&MI); 462bae20a6353583089224b94280a2dd69805dca247Evan Cheng AddDefaultPred(MIB); 463bae20a6353583089224b94280a2dd69805dca247Evan Cheng } 464a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 46574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 466a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 467a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ImmIdx = 0; 468a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int InstrOffs = 0; 469a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits = 0; 470a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Scale = 1; 471a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov switch (AddrMode) { 472055b0310f862b91f33699037ce67d3ab8137c20cEvan Cheng case ARMII::AddrModeT1_s: { 47374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach ImmIdx = FrameRegIdx+1; 474a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov InstrOffs = MI.getOperand(ImmIdx).getImm(); 475a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = (FrameReg == ARM::SP) ? 8 : 5; 476a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 477a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 478a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 479a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov default: 480c23197a26f34f559ea9797de51e187087c039c42Torok Edwin llvm_unreachable("Unsupported addressing mode!"); 481a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 482a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 483a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 484a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset += InstrOffs * Scale; 485a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); 486a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 487a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Common case: small offset, fits into instruction. 488a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineOperand &ImmOp = MI.getOperand(ImmIdx); 489a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ImmedOffset = Offset / Scale; 490a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Mask = (1 << NumBits) - 1; 491a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if ((unsigned)Offset <= Mask * Scale) { 492a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Replace the FrameIndex with sp 49374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 494a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(ImmedOffset); 49574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 496a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 497a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 498a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isThumSpillRestore = Opcode == ARM::tRestore || Opcode == ARM::tSpill; 499055b0310f862b91f33699037ce67d3ab8137c20cEvan Cheng if (AddrMode == ARMII::AddrModeT1_s) { 500a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Thumb tLDRspi, tSTRspi. These will change to instructions that use 501a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // a different base register. 502a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 5; 503a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Mask = (1 << NumBits) - 1; 504a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 505a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If this is a thumb spill / restore, we will be using a constpool load to 506a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // materialize the offset. 507055b0310f862b91f33699037ce67d3ab8137c20cEvan Cheng if (AddrMode == ARMII::AddrModeT1_s && isThumSpillRestore) 508a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(0); 509a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 510a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Otherwise, it didn't fit. Pull in what we can to simplify the immed. 511a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmedOffset = ImmedOffset & Mask; 512a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(ImmedOffset); 513a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset &= ~(Mask*Scale); 514a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 515a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 51674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return Offset == 0; 51774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach} 51874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 51974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachvoid 52074d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I, 52174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned BaseReg, int64_t Offset) const { 52274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineInstr &MI = *I; 52374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach int Off = Offset; // ARM doesn't need the general 64-bit offsets 52474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned i = 0; 52574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 52674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach while (!MI.getOperand(i).isFI()) { 52774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach ++i; 52874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 52974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 53074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach bool Done = false; 53174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII); 53274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert (Done && "Unable to resolve frame index!"); 53374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach} 53474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 53574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// saveScavengerRegister - Spill the register so it can be used by the 53674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// register scavenger. Return true. 53774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool 53874d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, 53974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineBasicBlock::iterator I, 54074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineBasicBlock::iterator &UseMI, 54174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const TargetRegisterClass *RC, 54274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned Reg) const { 54374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Thumb1 can't use the emergency spill slot on the stack because 54474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // ldr/str immediate offsets must be positive, and if we're referencing 54574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // off the frame pointer (if, for example, there are alloca() calls in 54674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // the function, the offset will be negative. Use R12 instead since that's 54774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // a call clobbered register that we know won't be used in Thumb1 mode. 54874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach DebugLoc DL; 54974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach BuildMI(MBB, I, DL, TII.get(ARM::tMOVtgpr2gpr)). 55074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach addReg(ARM::R12, RegState::Define).addReg(Reg, RegState::Kill); 55174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 55274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // The UseMI is where we would like to restore the register. If there's 55374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // interference with R12 before then, however, we'll need to restore it 55474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // before that instead and adjust the UseMI. 55574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach bool done = false; 55674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) { 55774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (II->isDebugValue()) 55874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach continue; 55974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // If this instruction affects R12, adjust our restore point. 56074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) { 56174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const MachineOperand &MO = II->getOperand(i); 56274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (!MO.isReg() || MO.isUndef() || !MO.getReg() || 56374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach TargetRegisterInfo::isVirtualRegister(MO.getReg())) 56474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach continue; 56574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (MO.getReg() == ARM::R12) { 56674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach UseMI = II; 56774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach done = true; 56874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach break; 56974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 57074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 57174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 57274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Restore the register from R12 57374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVgpr2tgpr)). 57474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill); 57574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 57674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 57774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach} 57874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 579fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbachvoid 58074d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 581fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach int SPAdj, RegScavenger *RS) const { 58274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned VReg = 0; 58374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned i = 0; 58474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineInstr &MI = *II; 58574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineBasicBlock &MBB = *MI.getParent(); 58674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineFunction &MF = *MBB.getParent(); 58774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 58874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach DebugLoc dl = MI.getDebugLoc(); 58974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 59074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach while (!MI.getOperand(i).isFI()) { 59174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach ++i; 59274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 59374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 59474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 59574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned FrameReg = ARM::SP; 59674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach int FrameIndex = MI.getOperand(i).getIndex(); 59774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + 59874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MF.getFrameInfo()->getStackSize() + SPAdj; 59974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 60074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (AFI->isGPRCalleeSavedArea1Frame(FrameIndex)) 60174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach Offset -= AFI->getGPRCalleeSavedArea1Offset(); 60274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach else if (AFI->isGPRCalleeSavedArea2Frame(FrameIndex)) 60374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach Offset -= AFI->getGPRCalleeSavedArea2Offset(); 60474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach else if (MF.getFrameInfo()->hasVarSizedObjects()) { 60574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert(SPAdj == 0 && hasFP(MF) && "Unexpected"); 60674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // There are alloca()'s in this function, must reference off the frame 60765482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach // pointer or base pointer instead. 60865482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach if (!hasBasePointer(MF)) { 60965482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach FrameReg = getFrameRegister(MF); 61065482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach Offset -= AFI->getFramePtrSpillOffset(); 61165482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach } else 61265482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach FrameReg = BasePtr; 61374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 61474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 61574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Special handling of dbg_value instructions. 61674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (MI.isDebugValue()) { 61774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(i). ChangeToRegister(FrameReg, false /*isDef*/); 61874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(i+1).ChangeToImmediate(Offset); 619fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach return; 62074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 62174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 62274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Modify MI as necessary to handle as much of 'Offset' as possible 62374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert(AFI->isThumbFunction() && 62474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach "This eliminateFrameIndex only supports Thumb1!"); 62574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (rewriteFrameIndex(MI, i, FrameReg, Offset, TII)) 626fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach return; 627a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 628a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If we get here, the immediate doesn't fit into the instruction. We folded 629a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // as much as possible above, handle the rest, providing a register that is 630a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // SP+LargeImm. 631a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(Offset && "This code isn't needed if offset already handled!"); 632a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 63374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned Opcode = MI.getOpcode(); 63474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const TargetInstrDesc &Desc = MI.getDesc(); 63574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 636446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng // Remove predicate first. 637446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng int PIdx = MI.findFirstPredOperandIdx(); 638446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (PIdx != -1) 639446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng removeOperands(MI, PIdx); 640446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 641a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Desc.mayLoad()) { 642a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Use the destination register to materialize sp + offset. 643a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned TmpReg = MI.getOperand(0).getReg(); 644a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool UseRR = false; 645a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opcode == ARM::tRestore) { 646a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (FrameReg == ARM::SP) 647a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, II, TmpReg, FrameReg, 648a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset, false, TII, *this, dl); 649a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 650378445303b10b092a898a75131141a8259cff50bEvan Cheng emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset); 651a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov UseRR = true; 652a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 653446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 654a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg, Offset, TII, 655a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov *this, dl); 656446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 657446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 658a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.setDesc(TII.get(ARM::tLDR)); 659a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(TmpReg, false, false, true); 660a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (UseRR) 661a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Use [reg, reg] addrmode. 662a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.addOperand(MachineOperand::CreateReg(FrameReg, false)); 663a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else // tLDR has an extra register operand. 664a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.addOperand(MachineOperand::CreateReg(0, false)); 665a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else if (Desc.mayStore()) { 666b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach VReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass); 6673d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach bool UseRR = false; 668b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach 6693d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach if (Opcode == ARM::tSpill) { 6703d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach if (FrameReg == ARM::SP) 671b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach emitThumbRegPlusImmInReg(MBB, II, VReg, FrameReg, 6723d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach Offset, false, TII, *this, dl); 6733d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach else { 674b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach emitLoadConstPool(MBB, II, dl, VReg, 0, Offset); 6753d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach UseRR = true; 6763d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach } 6773d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach } else 678b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach emitThumbRegPlusImmediate(MBB, II, VReg, FrameReg, Offset, TII, 6793d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach *this, dl); 6803d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach MI.setDesc(TII.get(ARM::tSTR)); 681b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach MI.getOperand(i).ChangeToRegister(VReg, false, false, true); 6823d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach if (UseRR) // Use [reg, reg] addrmode. 6833d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach MI.addOperand(MachineOperand::CreateReg(FrameReg, false)); 6843d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach else // tSTR has an extra register operand. 6853d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach MI.addOperand(MachineOperand::CreateReg(0, false)); 686a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else 687a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(false && "Unexpected opcode!"); 688446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 689446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng // Add predicate back if it's needed. 690446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (MI.getDesc().isPredicable()) { 691446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB(&MI); 692446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng AddDefaultPred(MIB); 693446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 694a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 695a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 696b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo::emitPrologue(MachineFunction &MF) const { 697a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock &MBB = MF.front(); 698a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator MBBI = MBB.begin(); 699a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFrameInfo *MFI = MF.getFrameInfo(); 700a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 701a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); 702a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBytes = MFI->getStackSize(); 703a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); 704c7f3ace20c325521c68335a1689645b43b06ddf0Chris Lattner DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 705a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 706a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4. 707a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = (NumBytes + 3) & ~3; 708a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MFI->setStackSize(NumBytes); 709a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 710a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Determine the sizes of each callee-save spill areas and record which frame 711a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // belongs to which callee-save spill areas. 712a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0; 713a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int FramePtrSpillFI = 0; 714a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 715a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (VARegSaveSize) 71655ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, -VARegSaveSize); 717a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 718a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!AFI->hasStackFrame()) { 719a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes != 0) 72055ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes); 721a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return; 722a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 723a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 724a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov for (unsigned i = 0, e = CSI.size(); i != e; ++i) { 725a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Reg = CSI[i].getReg(); 726a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int FI = CSI[i].getFrameIdx(); 727a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov switch (Reg) { 728a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R4: 729a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R5: 730a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R6: 731a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R7: 732a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::LR: 733a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Reg == FramePtr) 734a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov FramePtrSpillFI = FI; 735a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->addGPRCalleeSavedArea1Frame(FI); 736a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov GPRCS1Size += 4; 737a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 738a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R8: 739a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R9: 740a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R10: 741a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R11: 742a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Reg == FramePtr) 743a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov FramePtrSpillFI = FI; 744a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (STI.isTargetDarwin()) { 745a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->addGPRCalleeSavedArea2Frame(FI); 746a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov GPRCS2Size += 4; 747a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 748a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->addGPRCalleeSavedArea1Frame(FI); 749a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov GPRCS1Size += 4; 750a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 751a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 752a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov default: 753a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->addDPRCalleeSavedAreaFrame(FI); 754a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DPRCSSize += 8; 755a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 756a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 757a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 758a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) { 759a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ++MBBI; 760a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (MBBI != MBB.end()) 761a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov dl = MBBI->getDebugLoc(); 762a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 763a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 764ac096808a3accc516ae7c193c9a2c1392bf3301aEvan Cheng // Adjust FP so it point to the stack slot that contains the previous FP. 765ac096808a3accc516ae7c193c9a2c1392bf3301aEvan Cheng if (hasFP(MF)) { 766b7c5bdf843419e4222770475c27932c4c8e5c303Duncan Sands BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr) 767a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addFrameIndex(FramePtrSpillFI).addImm(0); 768ac096808a3accc516ae7c193c9a2c1392bf3301aEvan Cheng AFI->setShouldRestoreSPFromFP(true); 769a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 770a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 771a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Determine starting offsets of spill areas. 772a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize); 773a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; 774a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size; 775a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + NumBytes); 776a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); 777a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); 778a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); 779a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 780a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = DPRCSOffset; 781a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes) { 782a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Insert it after all the callee-save spills. 78355ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes); 784a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 785a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 786ac096808a3accc516ae7c193c9a2c1392bf3301aEvan Cheng if (STI.isTargetELF() && hasFP(MF)) 787a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() - 788a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->getFramePtrSpillOffset()); 789a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 790a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); 791a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setGPRCalleeSavedArea2Size(GPRCS2Size); 792a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setDPRCalleeSavedAreaSize(DPRCSSize); 79365482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach 79465482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach // If we need a base pointer, set it up here. It's whatever the value 79565482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach // of the stack pointer is at this point. Any variable size objects 79665482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach // will be allocated after this, so we can still use the base pointer 79765482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach // to reference locals. 79865482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach if (hasBasePointer(MF)) 79965482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), BasePtr).addReg(ARM::SP); 800a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 801a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 802a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) { 803a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov for (unsigned i = 0; CSRegs[i]; ++i) 804a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Reg == CSRegs[i]) 805a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return true; 806a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return false; 807a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 808a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 809a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) { 810e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach if (MI->getOpcode() == ARM::tRestore && 811e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach MI->getOperand(1).isFI() && 812e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs)) 813e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach return true; 814e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach else if (MI->getOpcode() == ARM::tPOP) { 815815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson // The first two operands are predicates. The last two are 816e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach // imp-def and imp-use of SP. Check everything in between. 817815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson for (int i = 2, e = MI->getNumOperands() - 2; i != e; ++i) 818e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach if (!isCalleeSavedRegister(MI->getOperand(i).getReg(), CSRegs)) 819e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach return false; 820e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach return true; 821e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach } 822e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach return false; 823a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 824a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 825b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo::emitEpilogue(MachineFunction &MF, 826b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin MachineBasicBlock &MBB) const { 827a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator MBBI = prior(MBB.end()); 828a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert((MBBI->getOpcode() == ARM::tBX_RET || 829a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBBI->getOpcode() == ARM::tPOP_RET) && 830a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov "Can only insert epilog into returning blocks"); 831a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = MBBI->getDebugLoc(); 832a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFrameInfo *MFI = MF.getFrameInfo(); 833a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 834a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); 835a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int NumBytes = (int)MFI->getStackSize(); 836e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach const unsigned *CSRegs = getCalleeSavedRegs(); 837a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 838a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!AFI->hasStackFrame()) { 839a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes != 0) 84055ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, NumBytes); 841a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 842e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach // Unwind MBBI to point to first LDR / VLDRD. 843a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (MBBI != MBB.begin()) { 844a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov do 845a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov --MBBI; 846a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov while (MBBI != MBB.begin() && isCSRestore(MBBI, CSRegs)); 847a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!isCSRestore(MBBI, CSRegs)) 848a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ++MBBI; 849a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 850a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 851a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Move SP to start of FP callee save spill area. 852a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes -= (AFI->getGPRCalleeSavedArea1Size() + 853a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->getGPRCalleeSavedArea2Size() + 854a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->getDPRCalleeSavedAreaSize()); 855a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 856ac096808a3accc516ae7c193c9a2c1392bf3301aEvan Cheng if (AFI->shouldRestoreSPFromFP()) { 857a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; 858a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Reset SP based on frame pointer only if the stack frame extends beyond 859a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // frame pointer stack slot or target is ELF and the function has FP. 860a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes) 861a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, FramePtr, -NumBytes, 862a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov TII, *this, dl); 863a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else 864d83360694a6d82772cf31a0be8a64570c2e5cb88Evan Cheng BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) 865a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(FramePtr); 866a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 867a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (MBBI->getOpcode() == ARM::tBX_RET && 868a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov &MBB.front() != MBBI && 869a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov prior(MBBI)->getOpcode() == ARM::tPOP) { 870a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator PMBBI = prior(MBBI); 87155ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, PMBBI, TII, dl, *this, NumBytes); 872a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else 87355ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, NumBytes); 874a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 875a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 876a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 877a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (VARegSaveSize) { 878004453e85e72a2a2ea9a70fc6b7b368feb877c4cJim Grosbach // Unlike T2 and ARM mode, the T1 pop instruction cannot restore 879004453e85e72a2a2ea9a70fc6b7b368feb877c4cJim Grosbach // to LR, and we can't pop the value directly to the PC since 880004453e85e72a2a2ea9a70fc6b7b368feb877c4cJim Grosbach // we need to update the SP after popping the value. Therefore, we 881004453e85e72a2a2ea9a70fc6b7b368feb877c4cJim Grosbach // pop the old LR into R3 as a temporary. 882004453e85e72a2a2ea9a70fc6b7b368feb877c4cJim Grosbach 883e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach // Move back past the callee-saved register restoration 884e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach while (MBBI != MBB.end() && isCSRestore(MBBI, CSRegs)) 885e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach ++MBBI; 886a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Epilogue for vararg functions: pop LR to R3 and branch off it. 8873d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP))) 8883d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach .addReg(ARM::R3, RegState::Define); 889a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 89055ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, VARegSaveSize); 891a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 8923d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg)) 8933d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach .addReg(ARM::R3, RegState::Kill); 894e68bd742451aae5fcdf280e823d2829e11d184daJim Grosbach // erase the old tBX_RET instruction 895a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBB.erase(MBBI); 896a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 897a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 898