Thumb1RegisterInfo.cpp revision 31c24bf5b39cc8391d4cfdbf8cf5163975fdb81e
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" 36ab7c09b6b6f4516a631fd6788918c237c83939afTorok Edwin#include "llvm/Support/ErrorHandling.h" 37dac237e18209b697a8ba122d0ddd9cad4dfba1f8Torok Edwin#include "llvm/Support/raw_ostream.h" 38a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovusing namespace llvm; 39a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 40db5a71a8e01ed9a0d93a19176df6ea0aea510d7bDavid GoodwinThumb1RegisterInfo::Thumb1RegisterInfo(const ARMBaseInstrInfo &tii, 41b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const ARMSubtarget &sti) 42a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov : ARMBaseRegisterInfo(tii, sti) { 43a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 44a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 45a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitLoadConstPool - Emits a load from constpool to materialize the 46a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// specified immediate. 47b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, 48b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin MachineBasicBlock::iterator &MBBI, 4977521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin DebugLoc dl, 50378445303b10b092a898a75131141a8259cff50bEvan Cheng unsigned DestReg, unsigned SubIdx, 51378445303b10b092a898a75131141a8259cff50bEvan Cheng int Val, 52db5a71a8e01ed9a0d93a19176df6ea0aea510d7bDavid Goodwin ARMCC::CondCodes Pred, 53db5a71a8e01ed9a0d93a19176df6ea0aea510d7bDavid Goodwin unsigned PredReg) const { 54a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFunction &MF = *MBB.getParent(); 55a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineConstantPool *ConstantPool = MF.getConstantPool(); 561d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson Constant *C = ConstantInt::get( 571d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val); 58a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); 59a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 60378445303b10b092a898a75131141a8259cff50bEvan Cheng BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRcp)) 61378445303b10b092a898a75131141a8259cff50bEvan Cheng .addReg(DestReg, getDefRegState(true), SubIdx) 62378445303b10b092a898a75131141a8259cff50bEvan Cheng .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg); 63a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 64a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 65a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovconst TargetRegisterClass* 66e50ed30282bb5b4a9ed952580523f2dda16215acOwen AndersonThumb1RegisterInfo::getPhysicalRegisterRegClass(unsigned Reg, EVT VT) const { 6755ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov if (isARMLowRegister(Reg)) 68a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return ARM::tGPRRegisterClass; 69a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov switch (Reg) { 70a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov default: 71a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 72a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R8: case ARM::R9: case ARM::R10: case ARM::R11: 73a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R12: case ARM::SP: case ARM::LR: case ARM::PC: 74a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return ARM::GPRRegisterClass; 75a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 76a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 77a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return TargetRegisterInfo::getPhysicalRegisterRegClass(Reg, VT); 78a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 79a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 80b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinbool Thumb1RegisterInfo::hasReservedCallFrame(MachineFunction &MF) const { 81a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const MachineFrameInfo *FFI = MF.getFrameInfo(); 82a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned CFSize = FFI->getMaxCallFrameSize(); 83a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // It's not always a good idea to include the call frame as part of the 84a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // stack frame. ARM (especially Thumb) has small immediate offset to 85a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // address the stack frame. So a large call frame can cause poor codegen 86a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // and may even makes it impossible to scavenge a register. 87a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (CFSize >= ((1 << 8) - 1) * 4 / 2) // Half of imm8 * 4 88a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return false; 89a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 90a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return !MF.getFrameInfo()->hasVarSizedObjects(); 91a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 92a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 93446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 94a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize 95a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// a destreg = basereg + immediate in Thumb code. Materialize the immediate 96a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// in a register using mov / mvn sequences or load the immediate from a 97a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constpool entry. 98a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic 99a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovvoid emitThumbRegPlusImmInReg(MachineBasicBlock &MBB, 100a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 101a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg, unsigned BaseReg, 102a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int NumBytes, bool CanChangeCC, 103a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrInfo &TII, 104b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo& MRI, 105a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl) { 1063d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach MachineFunction &MF = *MBB.getParent(); 10755ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov bool isHigh = !isARMLowRegister(DestReg) || 10855ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov (BaseReg != 0 && !isARMLowRegister(BaseReg)); 109a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = false; 110a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Subtract doesn't have high register version. Load the negative value 111a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // if either base or dest register is a high register. Also, if do not 112a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // issue sub as part of the sequence if condition register is to be 113a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // preserved. 114a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes < 0 && !isHigh && CanChangeCC) { 115a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isSub = true; 116a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = -NumBytes; 117a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 118a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned LdReg = DestReg; 119a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == ARM::SP) { 120a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(BaseReg == ARM::SP && "Unexpected!"); 12165c58daa8b8985d2116216043103009815a55e77Jim Grosbach LdReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass); 122a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 123a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 124a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes <= 255 && NumBytes >= 0) 125b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) 126446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addImm(NumBytes); 127a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else if (NumBytes < 0 && NumBytes >= -255) { 128b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) 129446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addImm(NumBytes); 130b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg)) 131a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(LdReg, RegState::Kill); 132a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else 133378445303b10b092a898a75131141a8259cff50bEvan Cheng MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes); 134a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 135a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Emit add / sub. 136a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr); 137446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB = 138446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); 139446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (Opc != ARM::tADDhirr) 140b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng MIB = AddDefaultT1CC(MIB); 141a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == ARM::SP || isSub) 142a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill); 143a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else 144a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill); 145446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng AddDefaultPred(MIB); 146a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 147a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 148a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// calcNumMI - Returns the number of instructions required to materialize 149a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// the specific add / sub r, c instruction. 150a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic unsigned calcNumMI(int Opc, int ExtraOpc, unsigned Bytes, 151a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits, unsigned Scale) { 152a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = 0; 153a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = ((1 << NumBits) - 1) * Scale; 154a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 155a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::tADDrSPi) { 156a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 157a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 158a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs++; 159a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 160a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 1; // Followed by a number of tADDi8. 161a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Chunk = ((1 << NumBits) - 1) * Scale; 162a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 163a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 164a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs += Bytes / Chunk; 165a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if ((Bytes % Chunk) != 0) 166a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs++; 167a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (ExtraOpc) 168a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs++; 169a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return NumMIs; 170a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 171a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 172a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize 173a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// a destreg = basereg + immediate in Thumb code. 174a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic 175a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovvoid emitThumbRegPlusImmediate(MachineBasicBlock &MBB, 176a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 177a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg, unsigned BaseReg, 178a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int NumBytes, const TargetInstrInfo &TII, 179b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo& MRI, 180a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl) { 181a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = NumBytes < 0; 182a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Bytes = (unsigned)NumBytes; 183a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (isSub) Bytes = -NumBytes; 184a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isMul4 = (Bytes & 3) == 0; 185a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isTwoAddr = false; 186a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool DstNotEqBase = false; 187a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits = 1; 188a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Scale = 1; 189a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Opc = 0; 190a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ExtraOpc = 0; 191446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng bool NeedCC = false; 192446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng bool NeedPred = false; 193a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 194a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == BaseReg && BaseReg == ARM::SP) { 195a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); 196a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 7; 197a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 198a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; 199a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isTwoAddr = true; 200a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else if (!isSub && BaseReg == ARM::SP) { 201a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add sp, 403 202a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // => 203a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add sp, 100 * 4 204a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add r1, 3 205a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!isMul4) { 206a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes &= ~3; 207a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ExtraOpc = ARM::tADDi3; 208a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 209a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 210a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 211a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = ARM::tADDrSPi; 212a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 213a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // sp = sub sp, c 214a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = sub sp, c 215a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r8 = sub sp, c 216a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg != BaseReg) 217a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DstNotEqBase = true; 218a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 219f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng if (DestReg == ARM::SP) { 220f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; 221f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); 222f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng NumBits = 7; 223f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Scale = 4; 224f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng } else { 225f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; 226f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng NumBits = 8; 227f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng NeedPred = NeedCC = true; 228f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng } 229a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isTwoAddr = true; 230a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 231a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 232a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale); 233a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2; 234a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumMIs > Threshold) { 235a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // This will expand into too many instructions. Load the immediate from a 236a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // constpool entry. 237a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, MBBI, DestReg, BaseReg, NumBytes, true, TII, 238a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MRI, dl); 239a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return; 240a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 241a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 242a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DstNotEqBase) { 24355ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov if (isARMLowRegister(DestReg) && isARMLowRegister(BaseReg)) { 244a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If both are low registers, emit DestReg = add BaseReg, max(Imm, 7) 245a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = (1 << 3) - 1; 246a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 247a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 248446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng const TargetInstrDesc &TID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); 249446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng const MachineInstrBuilder MIB = 250b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)); 251446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal)); 252a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 253a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) 254a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(BaseReg, RegState::Kill); 255a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 256a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BaseReg = DestReg; 257a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 258a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 259a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = ((1 << NumBits) - 1) * Scale; 260a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov while (Bytes) { 261a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 262a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 263a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ThisVal /= Scale; 264a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Build the new tADD / tSUB. 265446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (isTwoAddr) { 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(DestReg).addImm(ThisVal); 270446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedPred) 271446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MIB = AddDefaultPred(MIB); 272446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 273a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 274a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isKill = BaseReg != ARM::SP; 275446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); 276446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedCC) 277b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng MIB = AddDefaultT1CC(MIB); 278446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal); 279446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedPred) 280446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MIB = AddDefaultPred(MIB); 281a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BaseReg = DestReg; 282a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 283a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::tADDrSPi) { 284a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r4 = add sp, imm 285a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r4 = add r4, imm 286a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ... 287a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 288a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 1; 289a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Chunk = ((1 << NumBits) - 1) * Scale; 290a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; 291446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng NeedPred = NeedCC = isTwoAddr = true; 292a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 293a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 294a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 295a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 296446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (ExtraOpc) { 297446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng const TargetInstrDesc &TID = TII.get(ExtraOpc); 298b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)) 299446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addReg(DestReg, RegState::Kill) 300446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addImm(((unsigned)NumBytes) & 3)); 301446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 302a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 303a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 30455ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikovstatic void emitSPUpdate(MachineBasicBlock &MBB, 30555ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov MachineBasicBlock::iterator &MBBI, 30655ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov const TargetInstrInfo &TII, DebugLoc dl, 307b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo &MRI, 30855ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov int NumBytes) { 309a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, ARM::SP, NumBytes, TII, 31055ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov MRI, dl); 311a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 312a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 313b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo:: 314a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton KorobeynikoveliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 315a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator I) const { 316a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!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. 327a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Align = MF.getTarget().getFrameInfo()->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) 361a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, DestReg, DestReg, Imm, TII, MRI, dl); 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 3755ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwinint Thumb1RegisterInfo:: 3765ff58b5c3ab6df332600678798ea5c69c5e943d3David GoodwinrewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, 3776495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng unsigned FrameReg, int Offset, 378764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc) const 3795ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin{ 3805ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin // if/when eliminateFrameIndex() conforms with ARMBaseRegisterInfo 3815ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin // version then can pull out Thumb1 specific parts here 3825ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin return 0; 3835ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin} 3845ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin 385d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach/// saveScavengerRegister - Spill the register so it can be used by the 386540b05d227a79443b2a7b07d5152a35cb6392abfJim Grosbach/// register scavenger. Return true. 387d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbachbool 388d482f55af135081aee7f7ab972bb8973f189c88fJim GrosbachThumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, 389d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach MachineBasicBlock::iterator I, 390d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach MachineBasicBlock::iterator &UseMI, 391d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach const TargetRegisterClass *RC, 392d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach unsigned Reg) const { 393540b05d227a79443b2a7b07d5152a35cb6392abfJim Grosbach // Thumb1 can't use the emergency spill slot on the stack because 394540b05d227a79443b2a7b07d5152a35cb6392abfJim Grosbach // ldr/str immediate offsets must be positive, and if we're referencing 395540b05d227a79443b2a7b07d5152a35cb6392abfJim Grosbach // off the frame pointer (if, for example, there are alloca() calls in 396540b05d227a79443b2a7b07d5152a35cb6392abfJim Grosbach // the function, the offset will be negative. Use R12 instead since that's 397540b05d227a79443b2a7b07d5152a35cb6392abfJim Grosbach // a call clobbered register that we know won't be used in Thumb1 mode. 398d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach DebugLoc DL = DebugLoc::getUnknownLoc(); 399d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach BuildMI(MBB, I, DL, TII.get(ARM::tMOVtgpr2gpr)). 400d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach addReg(ARM::R12, RegState::Define).addReg(Reg, RegState::Kill); 401d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach 402d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach // The UseMI is where we would like to restore the register. If there's 403d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach // interference with R12 before then, however, we'll need to restore it 404d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach // before that instead and adjust the UseMI. 405d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach bool done = false; 406d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) { 407d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach // If this instruction affects R12, adjust our restore point. 408d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) { 409d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach const MachineOperand &MO = II->getOperand(i); 410d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach if (!MO.isReg() || MO.isUndef() || !MO.getReg() || 411d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach TargetRegisterInfo::isVirtualRegister(MO.getReg())) 412d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach continue; 413d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach if (MO.getReg() == ARM::R12) { 414d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach UseMI = II; 415d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach done = true; 416d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach break; 417d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach } 418d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach } 419d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach } 420d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach // Restore the register from R12 421d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVgpr2tgpr)). 422d482f55af135081aee7f7ab972bb8973f189c88fJim Grosbach addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill); 423540b05d227a79443b2a7b07d5152a35cb6392abfJim Grosbach 424540b05d227a79443b2a7b07d5152a35cb6392abfJim Grosbach return true; 425540b05d227a79443b2a7b07d5152a35cb6392abfJim Grosbach} 426540b05d227a79443b2a7b07d5152a35cb6392abfJim Grosbach 427b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbachunsigned 428b58f498f7502e7e1833decbbbb4df771367c7341Jim GrosbachThumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 429b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach int SPAdj, int *Value, 430b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach RegScavenger *RS) const{ 431b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach unsigned VReg = 0; 432a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned i = 0; 433a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineInstr &MI = *II; 434a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock &MBB = *MI.getParent(); 435a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFunction &MF = *MBB.getParent(); 436a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 437a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = MI.getDebugLoc(); 438a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 439a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov while (!MI.getOperand(i).isFI()) { 440a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ++i; 441a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 442a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 443a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 444a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned FrameReg = ARM::SP; 445a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int FrameIndex = MI.getOperand(i).getIndex(); 446a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + 447a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MF.getFrameInfo()->getStackSize() + SPAdj; 448a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 449a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (AFI->isGPRCalleeSavedArea1Frame(FrameIndex)) 450a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset -= AFI->getGPRCalleeSavedArea1Offset(); 451a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else if (AFI->isGPRCalleeSavedArea2Frame(FrameIndex)) 452a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset -= AFI->getGPRCalleeSavedArea2Offset(); 453a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else if (hasFP(MF)) { 454a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(SPAdj == 0 && "Unexpected"); 455a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // There is alloca()'s in this function, must reference off the frame 456a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // pointer instead. 457a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov FrameReg = getFrameRegister(MF); 458a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset -= AFI->getFramePtrSpillOffset(); 459a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 460a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 461a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Opcode = MI.getOpcode(); 462a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrDesc &Desc = MI.getDesc(); 463a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); 464a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 465a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opcode == ARM::tADDrSPi) { 466a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset += MI.getOperand(i+1).getImm(); 467a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 468a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Can't use tADDrSPi if it's based off the frame pointer. 469a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits = 0; 470a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Scale = 1; 471a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (FrameReg != ARM::SP) { 472a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opcode = ARM::tADDi3; 473446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MI.setDesc(TII.get(Opcode)); 474a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 3; 475a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 476a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 477a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 478a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert((Offset & 3) == 0 && 479a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov "Thumb add/sub sp, #imm immediate must be multiple of 4!"); 480a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 481a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 482a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Offset == 0) { 483a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Turn it into a move. 484d83360694a6d82772cf31a0be8a64570c2e5cb88Evan Cheng MI.setDesc(TII.get(ARM::tMOVgpr2tgpr)); 485a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(FrameReg, false); 486a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.RemoveOperand(i+1); 487b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach return 0; 488a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 489a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 490a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Common case: small offset, fits into instruction. 491a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Mask = (1 << NumBits) - 1; 492a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (((Offset / Scale) & ~Mask) == 0) { 493a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Replace the FrameIndex with sp / fp 494446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (Opcode == ARM::tADDi3) { 495446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng removeOperands(MI, i); 496446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB(&MI); 497b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg) 498f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng .addImm(Offset / Scale)); 499446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 500446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MI.getOperand(i).ChangeToRegister(FrameReg, false); 501446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MI.getOperand(i+1).ChangeToImmediate(Offset / Scale); 502446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 503b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach return 0; 504a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 505a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 506a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg = MI.getOperand(0).getReg(); 507a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Bytes = (Offset > 0) ? Offset : -Offset; 508a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = calcNumMI(Opcode, 0, Bytes, NumBits, Scale); 509a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // MI would expand into a large number of instructions. Don't try to 510a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // simplify the immediate. 511a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumMIs > 2) { 512a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, II, DestReg, FrameReg, Offset, TII, 513a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov *this, dl); 514a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBB.erase(II); 515b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach return 0; 516a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 517a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 518a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Offset > 0) { 519a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Translate r0 = add sp, imm to 520a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add sp, 255*4 521a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add r0, (imm - 255*4) 522446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (Opcode == ARM::tADDi3) { 523446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng removeOperands(MI, i); 524446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB(&MI); 525b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg).addImm(Mask)); 526446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 527446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MI.getOperand(i).ChangeToRegister(FrameReg, false); 528446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MI.getOperand(i+1).ChangeToImmediate(Mask); 529446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 530a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset = (Offset - Mask * Scale); 531a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator NII = next(II); 532a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, NII, DestReg, DestReg, Offset, TII, 533a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov *this, dl); 534a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 535a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Translate r0 = add sp, -imm to 536a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = -imm (this is then translated into a series of instructons) 537a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add r0, sp 538a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbConstant(MBB, II, DestReg, Offset, TII, *this, dl); 539bae20a6353583089224b94280a2dd69805dca247Evan Cheng 540a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.setDesc(TII.get(ARM::tADDhirr)); 541a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(DestReg, false, false, true); 542a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i+1).ChangeToRegister(FrameReg, false); 543bae20a6353583089224b94280a2dd69805dca247Evan Cheng if (Opcode == ARM::tADDi3) { 544bae20a6353583089224b94280a2dd69805dca247Evan Cheng MachineInstrBuilder MIB(&MI); 545bae20a6353583089224b94280a2dd69805dca247Evan Cheng AddDefaultPred(MIB); 546bae20a6353583089224b94280a2dd69805dca247Evan Cheng } 547a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 548b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach return 0; 549a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 550a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ImmIdx = 0; 551a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int InstrOffs = 0; 552a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits = 0; 553a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Scale = 1; 554a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov switch (AddrMode) { 555055b0310f862b91f33699037ce67d3ab8137c20cEvan Cheng case ARMII::AddrModeT1_s: { 556a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmIdx = i+1; 557a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov InstrOffs = MI.getOperand(ImmIdx).getImm(); 558a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = (FrameReg == ARM::SP) ? 8 : 5; 559a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 560a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 561a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 562a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov default: 563c23197a26f34f559ea9797de51e187087c039c42Torok Edwin llvm_unreachable("Unsupported addressing mode!"); 564a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 565a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 566a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 567a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset += InstrOffs * Scale; 568a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); 569a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 570a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Common case: small offset, fits into instruction. 571a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineOperand &ImmOp = MI.getOperand(ImmIdx); 572a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ImmedOffset = Offset / Scale; 573a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Mask = (1 << NumBits) - 1; 574a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if ((unsigned)Offset <= Mask * Scale) { 575a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Replace the FrameIndex with sp 576a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(FrameReg, false); 577a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(ImmedOffset); 578b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach return 0; 579a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 580a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 581a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isThumSpillRestore = Opcode == ARM::tRestore || Opcode == ARM::tSpill; 582055b0310f862b91f33699037ce67d3ab8137c20cEvan Cheng if (AddrMode == ARMII::AddrModeT1_s) { 583a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Thumb tLDRspi, tSTRspi. These will change to instructions that use 584a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // a different base register. 585a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 5; 586a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Mask = (1 << NumBits) - 1; 587a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 588a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If this is a thumb spill / restore, we will be using a constpool load to 589a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // materialize the offset. 590055b0310f862b91f33699037ce67d3ab8137c20cEvan Cheng if (AddrMode == ARMII::AddrModeT1_s && isThumSpillRestore) 591a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(0); 592a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 593a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Otherwise, it didn't fit. Pull in what we can to simplify the immed. 594a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmedOffset = ImmedOffset & Mask; 595a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(ImmedOffset); 596a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset &= ~(Mask*Scale); 597a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 598a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 599a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 600a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If we get here, the immediate doesn't fit into the instruction. We folded 601a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // as much as possible above, handle the rest, providing a register that is 602a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // SP+LargeImm. 603a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(Offset && "This code isn't needed if offset already handled!"); 604a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 605446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng // Remove predicate first. 606446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng int PIdx = MI.findFirstPredOperandIdx(); 607446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (PIdx != -1) 608446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng removeOperands(MI, PIdx); 609446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 610a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Desc.mayLoad()) { 611a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Use the destination register to materialize sp + offset. 612a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned TmpReg = MI.getOperand(0).getReg(); 613a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool UseRR = false; 614a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opcode == ARM::tRestore) { 615a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (FrameReg == ARM::SP) 616a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, II, TmpReg, FrameReg, 617a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset, false, TII, *this, dl); 618a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 619378445303b10b092a898a75131141a8259cff50bEvan Cheng emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset); 620a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov UseRR = true; 621a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 622446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 623a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg, Offset, TII, 624a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov *this, dl); 625446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 626446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 627a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.setDesc(TII.get(ARM::tLDR)); 628a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(TmpReg, false, false, true); 629a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (UseRR) 630a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Use [reg, reg] addrmode. 631a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.addOperand(MachineOperand::CreateReg(FrameReg, false)); 632a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else // tLDR has an extra register operand. 633a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.addOperand(MachineOperand::CreateReg(0, false)); 634a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else if (Desc.mayStore()) { 635b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach VReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass); 636b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach assert (Value && "Frame index virtual allocated, but Value arg is NULL!"); 637b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach *Value = Offset; 6383d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach bool UseRR = false; 639b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach 6403d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach if (Opcode == ARM::tSpill) { 6413d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach if (FrameReg == ARM::SP) 642b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach emitThumbRegPlusImmInReg(MBB, II, VReg, FrameReg, 6433d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach Offset, false, TII, *this, dl); 6443d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach else { 645b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach emitLoadConstPool(MBB, II, dl, VReg, 0, Offset); 6463d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach UseRR = true; 6473d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach } 6483d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach } else 649b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach emitThumbRegPlusImmediate(MBB, II, VReg, FrameReg, Offset, TII, 6503d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach *this, dl); 6513d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach MI.setDesc(TII.get(ARM::tSTR)); 652b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach MI.getOperand(i).ChangeToRegister(VReg, false, false, true); 6533d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach if (UseRR) // Use [reg, reg] addrmode. 6543d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach MI.addOperand(MachineOperand::CreateReg(FrameReg, false)); 6553d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach else // tSTR has an extra register operand. 6563d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach MI.addOperand(MachineOperand::CreateReg(0, false)); 657a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else 658a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(false && "Unexpected opcode!"); 659446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 660446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng // Add predicate back if it's needed. 661446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (MI.getDesc().isPredicable()) { 662446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB(&MI); 663446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng AddDefaultPred(MIB); 664446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 665b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach return VReg; 666a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 667a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 668b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo::emitPrologue(MachineFunction &MF) const { 669a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock &MBB = MF.front(); 670a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator MBBI = MBB.begin(); 671a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFrameInfo *MFI = MF.getFrameInfo(); 672a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 673a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); 674a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBytes = MFI->getStackSize(); 675a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); 676a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = (MBBI != MBB.end() ? 677a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBBI->getDebugLoc() : DebugLoc::getUnknownLoc()); 678a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 679a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4. 680a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = (NumBytes + 3) & ~3; 681a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MFI->setStackSize(NumBytes); 682a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 683a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Determine the sizes of each callee-save spill areas and record which frame 684a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // belongs to which callee-save spill areas. 685a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0; 686a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int FramePtrSpillFI = 0; 687a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 688a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (VARegSaveSize) 68955ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, -VARegSaveSize); 690a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 691a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!AFI->hasStackFrame()) { 692a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes != 0) 69355ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes); 694a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return; 695a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 696a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 697a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov for (unsigned i = 0, e = CSI.size(); i != e; ++i) { 698a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Reg = CSI[i].getReg(); 699a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int FI = CSI[i].getFrameIdx(); 700a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov switch (Reg) { 701a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R4: 702a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R5: 703a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R6: 704a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R7: 705a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::LR: 706a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Reg == FramePtr) 707a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov FramePtrSpillFI = FI; 708a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->addGPRCalleeSavedArea1Frame(FI); 709a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov GPRCS1Size += 4; 710a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 711a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R8: 712a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R9: 713a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R10: 714a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R11: 715a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Reg == FramePtr) 716a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov FramePtrSpillFI = FI; 717a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (STI.isTargetDarwin()) { 718a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->addGPRCalleeSavedArea2Frame(FI); 719a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov GPRCS2Size += 4; 720a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 721a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->addGPRCalleeSavedArea1Frame(FI); 722a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov GPRCS1Size += 4; 723a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 724a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 725a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov default: 726a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->addDPRCalleeSavedAreaFrame(FI); 727a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DPRCSSize += 8; 728a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 729a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 730a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 731a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) { 732a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ++MBBI; 733a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (MBBI != MBB.end()) 734a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov dl = MBBI->getDebugLoc(); 735a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 736a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 737a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Darwin ABI requires FP to point to the stack slot that contains the 738a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // previous FP. 739a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (STI.isTargetDarwin() || hasFP(MF)) { 740b7c5bdf843419e4222770475c27932c4c8e5c303Duncan Sands BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr) 741a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addFrameIndex(FramePtrSpillFI).addImm(0); 742a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 743a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 744a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Determine starting offsets of spill areas. 745a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize); 746a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; 747a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size; 748a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + NumBytes); 749a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); 750a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); 751a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); 752a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 753a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = DPRCSOffset; 754a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes) { 755a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Insert it after all the callee-save spills. 75655ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes); 757a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 758a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 759a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (STI.isTargetELF() && hasFP(MF)) { 760a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() - 761a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->getFramePtrSpillOffset()); 762a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 763a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 764a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); 765a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setGPRCalleeSavedArea2Size(GPRCS2Size); 766a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setDPRCalleeSavedAreaSize(DPRCSSize); 767a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 768a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 769a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) { 770a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov for (unsigned i = 0; CSRegs[i]; ++i) 771a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Reg == CSRegs[i]) 772a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return true; 773a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return false; 774a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 775a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 776a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) { 777a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return (MI->getOpcode() == ARM::tRestore && 778a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI->getOperand(1).isFI() && 779a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs)); 780a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 781a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 782b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo::emitEpilogue(MachineFunction &MF, 783b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin MachineBasicBlock &MBB) const { 784a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator MBBI = prior(MBB.end()); 785a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert((MBBI->getOpcode() == ARM::tBX_RET || 786a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBBI->getOpcode() == ARM::tPOP_RET) && 787a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov "Can only insert epilog into returning blocks"); 788a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = MBBI->getDebugLoc(); 789a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFrameInfo *MFI = MF.getFrameInfo(); 790a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 791a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); 792a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int NumBytes = (int)MFI->getStackSize(); 793a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 794a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!AFI->hasStackFrame()) { 795a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes != 0) 79655ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, NumBytes); 797a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 798a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Unwind MBBI to point to first LDR / FLDD. 799a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const unsigned *CSRegs = getCalleeSavedRegs(); 800a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (MBBI != MBB.begin()) { 801a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov do 802a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov --MBBI; 803a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov while (MBBI != MBB.begin() && isCSRestore(MBBI, CSRegs)); 804a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!isCSRestore(MBBI, CSRegs)) 805a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ++MBBI; 806a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 807a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 808a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Move SP to start of FP callee save spill area. 809a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes -= (AFI->getGPRCalleeSavedArea1Size() + 810a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->getGPRCalleeSavedArea2Size() + 811a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->getDPRCalleeSavedAreaSize()); 812a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 813a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (hasFP(MF)) { 814a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; 815a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Reset SP based on frame pointer only if the stack frame extends beyond 816a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // frame pointer stack slot or target is ELF and the function has FP. 817a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes) 818a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, FramePtr, -NumBytes, 819a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov TII, *this, dl); 820a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else 821d83360694a6d82772cf31a0be8a64570c2e5cb88Evan Cheng BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) 822a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(FramePtr); 823a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 824a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (MBBI->getOpcode() == ARM::tBX_RET && 825a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov &MBB.front() != MBBI && 826a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov prior(MBBI)->getOpcode() == ARM::tPOP) { 827a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator PMBBI = prior(MBBI); 82855ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, PMBBI, TII, dl, *this, NumBytes); 829a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else 83055ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, NumBytes); 831a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 832a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 833a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 834a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (VARegSaveSize) { 835a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Epilogue for vararg functions: pop LR to R3 and branch off it. 8363d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP))) 83710469f8e48e007989b0469e677d4000a1311ecd2Evan Cheng .addReg(0) // No write back. 8383d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach .addReg(ARM::R3, RegState::Define); 839a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 84055ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, VARegSaveSize); 841a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 8423d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg)) 8433d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach .addReg(ARM::R3, RegState::Kill); 844a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBB.erase(MBBI); 845a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 846a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 847