131d157ae1ac2cd9c787dc3c1d28e64c682803844Jia Liu//===-- Thumb1RegisterInfo.cpp - Thumb-1 Register Information -------------===// 2a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 3a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// The LLVM Compiler Infrastructure 4a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 5a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// This file is distributed under the University of Illinois Open Source 6a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// License. See LICENSE.TXT for details. 7a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 8a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//===----------------------------------------------------------------------===// 9a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 1031c24bf5b39cc8391d4cfdbf8cf5163975fdb81eJim Grosbach// This file contains the Thumb-1 implementation of the TargetRegisterInfo 1131c24bf5b39cc8391d4cfdbf8cf5163975fdb81eJim Grosbach// class. 12a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 13a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//===----------------------------------------------------------------------===// 14a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 15c1f6f42049696e7357fb4837e1b25dabbaed3fe6Craig Topper#include "Thumb1RegisterInfo.h" 1677521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin#include "ARMBaseInstrInfo.h" 17a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMMachineFunctionInfo.h" 18a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMSubtarget.h" 19ee04a6d3a40c3017124e3fd89a0db473a2824498Evan Cheng#include "MCTargetDesc/ARMAddressingModes.h" 20a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineConstantPool.h" 21a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineFrameInfo.h" 22a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineFunction.h" 23a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineInstrBuilder.h" 24a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineRegisterInfo.h" 250f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen#include "llvm/CodeGen/RegisterScavenging.h" 260b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Constants.h" 270b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DerivedTypes.h" 280b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Function.h" 290b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/LLVMContext.h" 304e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach#include "llvm/Support/CommandLine.h" 31ab7c09b6b6f4516a631fd6788918c237c83939afTorok Edwin#include "llvm/Support/ErrorHandling.h" 32d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Target/TargetFrameLowering.h" 33d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Target/TargetMachine.h" 34a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 358c407d45964fbba19719be555324f247e4fb14e1Dan Gohmannamespace llvm { 364e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbachextern cl::opt<bool> ReuseFrameIndexVals; 378c407d45964fbba19719be555324f247e4fb14e1Dan Gohman} 388c407d45964fbba19719be555324f247e4fb14e1Dan Gohman 398c407d45964fbba19719be555324f247e4fb14e1Dan Gohmanusing namespace llvm; 404e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach 4157148c166ab232191098492633c924fad9c44ef3Bill WendlingThumb1RegisterInfo::Thumb1RegisterInfo(const ARMSubtarget &sti) 4257148c166ab232191098492633c924fad9c44ef3Bill Wendling : ARMBaseRegisterInfo(sti) { 43a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 44a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 45c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesenconst TargetRegisterClass* 46c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund OlesenThumb1RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) 47c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen const { 48fa226bccaa90c520cac154df74069bbabb976eabJakob Stoklund Olesen if (ARM::tGPRRegClass.hasSubClassEq(RC)) 49420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper return &ARM::tGPRRegClass; 50c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC); 51c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen} 52c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen 531db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesenconst TargetRegisterClass * 54397fc4874efe9c17e737d4c5c50bd19dc3bf27f5Jakob Stoklund OlesenThumb1RegisterInfo::getPointerRegClass(const MachineFunction &MF, unsigned Kind) 55397fc4874efe9c17e737d4c5c50bd19dc3bf27f5Jakob Stoklund Olesen const { 56420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper return &ARM::tGPRRegClass; 571db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesen} 581db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesen 59a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitLoadConstPool - Emits a load from constpool to materialize the 60a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// specified immediate. 613daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikovvoid 623daccd82d3151fa3629de430b55698a81084fc9eAnton KorobeynikovThumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, 633daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 643daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov DebugLoc dl, 653daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov unsigned DestReg, unsigned SubIdx, 663daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov int Val, 673daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov ARMCC::CondCodes Pred, unsigned PredReg, 683daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov unsigned MIFlags) const { 69a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFunction &MF = *MBB.getParent(); 7057148c166ab232191098492633c924fad9c44ef3Bill Wendling const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 71a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineConstantPool *ConstantPool = MF.getConstantPool(); 7246510a73e977273ec67747eb34cbdb43f815e451Dan Gohman const Constant *C = ConstantInt::get( 731d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val); 74a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); 75a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 763e333637f172c30adf5c8333b592fbde17ff9f78Jim Grosbach BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRpci)) 77b3fcc06d2124f9d01e3b48097b44cc141309908eAnton Korobeynikov .addReg(DestReg, getDefRegState(true), SubIdx) 78b3fcc06d2124f9d01e3b48097b44cc141309908eAnton Korobeynikov .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg) 79b3fcc06d2124f9d01e3b48097b44cc141309908eAnton Korobeynikov .setMIFlags(MIFlags); 80a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 81a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 82446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 83a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize 84a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// a destreg = basereg + immediate in Thumb code. Materialize the immediate 85a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// in a register using mov / mvn sequences or load the immediate from a 86a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constpool entry. 87a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic 88a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovvoid emitThumbRegPlusImmInReg(MachineBasicBlock &MBB, 89a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 903daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov DebugLoc dl, 91a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg, unsigned BaseReg, 92a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int NumBytes, bool CanChangeCC, 93a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrInfo &TII, 94e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach const ARMBaseRegisterInfo& MRI, 953daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov unsigned MIFlags = MachineInstr::NoFlags) { 963d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach MachineFunction &MF = *MBB.getParent(); 9755ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov bool isHigh = !isARMLowRegister(DestReg) || 9855ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov (BaseReg != 0 && !isARMLowRegister(BaseReg)); 99a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = false; 100a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Subtract doesn't have high register version. Load the negative value 101a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // if either base or dest register is a high register. Also, if do not 102a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // issue sub as part of the sequence if condition register is to be 103a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // preserved. 104a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes < 0 && !isHigh && CanChangeCC) { 105a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isSub = true; 106a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = -NumBytes; 107a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 108a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned LdReg = DestReg; 109a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == ARM::SP) { 110a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(BaseReg == ARM::SP && "Unexpected!"); 111420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper LdReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass); 112a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 113a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 114a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes <= 255 && NumBytes >= 0) 115b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) 1163daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .addImm(NumBytes).setMIFlags(MIFlags); 117a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else if (NumBytes < 0 && NumBytes >= -255) { 118b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) 1193daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .addImm(NumBytes).setMIFlags(MIFlags); 120b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg)) 1213daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .addReg(LdReg, RegState::Kill).setMIFlags(MIFlags); 122a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else 1233daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes, 1243daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov ARMCC::AL, 0, MIFlags); 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. 165e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbachvoid llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, 166e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach MachineBasicBlock::iterator &MBBI, 16757caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov DebugLoc dl, 168e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach unsigned DestReg, unsigned BaseReg, 169e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach int NumBytes, const TargetInstrInfo &TII, 1703daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov const ARMBaseRegisterInfo& MRI, 1713daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov unsigned MIFlags) { 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; 183a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 184a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == BaseReg && BaseReg == ARM::SP) { 185a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); 186a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 7; 187a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 188a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; 189a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isTwoAddr = true; 190a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else if (!isSub && BaseReg == ARM::SP) { 191a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add sp, 403 192a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // => 193a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add sp, 100 * 4 194a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add r1, 3 195a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!isMul4) { 196a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes &= ~3; 197a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ExtraOpc = ARM::tADDi3; 198a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 199a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 200a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 201a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = ARM::tADDrSPi; 202a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 203a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // sp = sub sp, c 204a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = sub sp, c 205a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r8 = sub sp, c 206a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg != BaseReg) 207a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DstNotEqBase = true; 208a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 209f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng if (DestReg == ARM::SP) { 210f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; 211f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); 212f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng NumBits = 7; 213f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Scale = 4; 214f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng } else { 215f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; 216f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng NumBits = 8; 2175b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach NeedCC = true; 218f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng } 219a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isTwoAddr = true; 220a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 221a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 222a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale); 223a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2; 224a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumMIs > Threshold) { 225a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // This will expand into too many instructions. Load the immediate from a 226a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // constpool entry. 2273daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, MBBI, dl, 2283daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov DestReg, BaseReg, NumBytes, true, 2293daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov TII, MRI, MIFlags); 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; 239e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng const MCInstrDesc &MCID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); 240446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng const MachineInstrBuilder MIB = 2414372ca6fe4119d708d43d9c9ac3feafc7607952aJim Grosbach AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg) 2424372ca6fe4119d708d43d9c9ac3feafc7607952aJim Grosbach .setMIFlags(MIFlags)); 243446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal)); 244a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 24563b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) 24663b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach .addReg(BaseReg, RegState::Kill)) 2473daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .setMIFlags(MIFlags); 248a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 249a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BaseReg = DestReg; 250a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 251a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 252a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = ((1 << NumBits) - 1) * Scale; 253a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov while (Bytes) { 254a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 255a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 256a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ThisVal /= Scale; 257a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Build the new tADD / tSUB. 258446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (isTwoAddr) { 259446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); 260446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedCC) 261b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng MIB = AddDefaultT1CC(MIB); 2623daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov MIB.addReg(DestReg).addImm(ThisVal); 2635b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach MIB = AddDefaultPred(MIB); 2643daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov MIB.setMIFlags(MIFlags); 2658884148b8e8f19d5484e735618cf188cfa02c626Jim Grosbach } else { 266a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isKill = BaseReg != ARM::SP; 267446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); 268446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedCC) 269b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng MIB = AddDefaultT1CC(MIB); 270446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal); 2715b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach MIB = AddDefaultPred(MIB); 2723daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov MIB.setMIFlags(MIFlags); 273a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 2743daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov BaseReg = DestReg; 275a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::tADDrSPi) { 276a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r4 = add sp, imm 277a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r4 = add r4, imm 278a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ... 279a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 280a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 1; 281a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Chunk = ((1 << NumBits) - 1) * Scale; 282a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; 2835b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach NeedCC = isTwoAddr = true; 284a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 285a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 286a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 287a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 288446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (ExtraOpc) { 289e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng const MCInstrDesc &MCID = TII.get(ExtraOpc); 290e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)) 291446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addReg(DestReg, RegState::Kill) 2923daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .addImm(((unsigned)NumBytes) & 3) 2933daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .setMIFlags(MIFlags)); 294446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 295a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 296a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 297a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbConstant - Emit a series of instructions to materialize a 298a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constant. 299a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic void emitThumbConstant(MachineBasicBlock &MBB, 300a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 301a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg, int Imm, 302a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrInfo &TII, 303b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo& MRI, 304a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl) { 305a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = Imm < 0; 306a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (isSub) Imm = -Imm; 307a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 308a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Chunk = (1 << 8) - 1; 309a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ThisVal = (Imm > Chunk) ? Chunk : Imm; 310a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Imm -= ThisVal; 311b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), 312b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng DestReg)) 313446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addImm(ThisVal)); 314a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Imm > 0) 31557caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, dl, DestReg, DestReg, Imm, TII, MRI); 316446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (isSub) { 317e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng const MCInstrDesc &MCID = TII.get(ARM::tRSB); 318e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)) 319446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addReg(DestReg, RegState::Kill)); 320446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 321446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng} 322446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 323446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Chengstatic void removeOperands(MachineInstr &MI, unsigned i) { 324446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng unsigned Op = i; 325446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng for (unsigned e = MI.getNumOperands(); i != e; ++i) 326446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MI.RemoveOperand(Op); 327a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 328a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 3297a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling/// convertToNonSPOpcode - Change the opcode to the non-SP version, because 3307a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling/// we're replacing the frame index with a non-SP register. 3317a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendlingstatic unsigned convertToNonSPOpcode(unsigned Opcode) { 3327a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling switch (Opcode) { 3337a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling case ARM::tLDRspi: 3347a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling return ARM::tLDRi; 3357a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 3367a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling case ARM::tSTRspi: 3377a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling return ARM::tSTRi; 3387a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling } 3397a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 3407a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling return Opcode; 3417a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling} 3427a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 34374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool Thumb1RegisterInfo:: 34474d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachrewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, 34574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned FrameReg, int &Offset, 34674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const ARMBaseInstrInfo &TII) const { 347a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineInstr &MI = *II; 348a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock &MBB = *MI.getParent(); 349a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = MI.getDebugLoc(); 35037a942cd52725b1d390989a8267a764b42fcb5d3Jakob Stoklund Olesen MachineInstrBuilder MIB(*MBB.getParent(), &MI); 351a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Opcode = MI.getOpcode(); 352e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng const MCInstrDesc &Desc = MI.getDesc(); 353a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); 354a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 355a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opcode == ARM::tADDrSPi) { 35674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach Offset += MI.getOperand(FrameRegIdx+1).getImm(); 357a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 358a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Can't use tADDrSPi if it's based off the frame pointer. 359a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits = 0; 360a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Scale = 1; 361a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (FrameReg != ARM::SP) { 362a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opcode = ARM::tADDi3; 363a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 3; 364a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 365a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 366a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 367a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert((Offset & 3) == 0 && 368a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov "Thumb add/sub sp, #imm immediate must be multiple of 4!"); 369a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 370a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 37135f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen unsigned PredReg; 37235f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) { 373a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Turn it into a move. 3742a7b41ba4d3eb3c6003f6768dc20b28d83eac265Jim Grosbach MI.setDesc(TII.get(ARM::tMOVr)); 37574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 3765b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach // Remove offset 37763b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach MI.RemoveOperand(FrameRegIdx+1); 37874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 379a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 380a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 381a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Common case: small offset, fits into instruction. 382a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Mask = (1 << NumBits) - 1; 383a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (((Offset / Scale) & ~Mask) == 0) { 384a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Replace the FrameIndex with sp / fp 385446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (Opcode == ARM::tADDi3) { 3865b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach MI.setDesc(TII.get(Opcode)); 38774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach removeOperands(MI, FrameRegIdx); 388b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg) 389f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng .addImm(Offset / Scale)); 390446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 39174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 39274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset / Scale); 393446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 39474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 395a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 396a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 397a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg = MI.getOperand(0).getReg(); 398a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Bytes = (Offset > 0) ? Offset : -Offset; 399a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = calcNumMI(Opcode, 0, Bytes, NumBits, Scale); 400a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // MI would expand into a large number of instructions. Don't try to 401a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // simplify the immediate. 402a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumMIs > 2) { 40357caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII, 40457caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov *this); 405a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBB.erase(II); 40674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 407a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 408a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 409a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Offset > 0) { 410a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Translate r0 = add sp, imm to 411a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add sp, 255*4 412a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add r0, (imm - 255*4) 413446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (Opcode == ARM::tADDi3) { 41429b9d7e4ea7521be25bccdb66ecd9c9df5ed8b4bChad Rosier MI.setDesc(TII.get(Opcode)); 41574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach removeOperands(MI, FrameRegIdx); 416b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg).addImm(Mask)); 417446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 41874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 41974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Mask); 420446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 421a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset = (Offset - Mask * Scale); 42236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MachineBasicBlock::iterator NII = std::next(II); 42357caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, NII, dl, DestReg, DestReg, Offset, TII, 42457caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov *this); 425a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 426a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Translate r0 = add sp, -imm to 4273f4f420ab7acb10221ba971543a7eed5489fb626Robert Wilhelm // r0 = -imm (this is then translated into a series of instructions) 428a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add r0, sp 429a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbConstant(MBB, II, DestReg, Offset, TII, *this, dl); 430bae20a6353583089224b94280a2dd69805dca247Evan Cheng 431a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.setDesc(TII.get(ARM::tADDhirr)); 43274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false, false, true); 43374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx+1).ChangeToRegister(FrameReg, false); 434a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 43574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 436a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 4377a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling if (AddrMode != ARMII::AddrModeT1_s) 438c23197a26f34f559ea9797de51e187087c039c42Torok Edwin llvm_unreachable("Unsupported addressing mode!"); 4397a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 4407a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling unsigned ImmIdx = FrameRegIdx + 1; 4417a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling int InstrOffs = MI.getOperand(ImmIdx).getImm(); 4427a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5; 4437a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling unsigned Scale = 4; 444a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 445a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset += InstrOffs * Scale; 4467a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!"); 447a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 448a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Common case: small offset, fits into instruction. 449a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineOperand &ImmOp = MI.getOperand(ImmIdx); 450a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ImmedOffset = Offset / Scale; 451a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Mask = (1 << NumBits) - 1; 4527a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 453a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if ((unsigned)Offset <= Mask * Scale) { 4547a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling // Replace the FrameIndex with the frame register (e.g., sp). 45574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 456a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(ImmedOffset); 4577a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 4587a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling // If we're using a register where sp was stored, convert the instruction 4597a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling // to the non-SP version. 4607a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling unsigned NewOpc = convertToNonSPOpcode(Opcode); 4617a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling if (NewOpc != Opcode && FrameReg != ARM::SP) 4627a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling MI.setDesc(TII.get(NewOpc)); 4637a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 46474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 465a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 466a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 4677a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling NumBits = 5; 4687a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling Mask = (1 << NumBits) - 1; 4697a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 470a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If this is a thumb spill / restore, we will be using a constpool load to 471a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // materialize the offset. 47274472b4bf963c424da04f42dffdb94c85ef964bcJim Grosbach if (Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) { 473a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(0); 4747a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling } else { 475a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Otherwise, it didn't fit. Pull in what we can to simplify the immed. 476a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmedOffset = ImmedOffset & Mask; 477a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(ImmedOffset); 4787a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling Offset &= ~(Mask * Scale); 479a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 480a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 4817a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 48274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return Offset == 0; 48374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach} 48474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 48536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid Thumb1RegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg, 48636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int64_t Offset) const { 48757148c166ab232191098492633c924fad9c44ef3Bill Wendling const ARMBaseInstrInfo &TII = 48857148c166ab232191098492633c924fad9c44ef3Bill Wendling *static_cast<const ARMBaseInstrInfo*>( 48957148c166ab232191098492633c924fad9c44ef3Bill Wendling MI.getParent()->getParent()->getTarget().getInstrInfo()); 49074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach int Off = Offset; // ARM doesn't need the general 64-bit offsets 49174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned i = 0; 49274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 49374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach while (!MI.getOperand(i).isFI()) { 49474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach ++i; 49574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 49674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 4971f6a329f79b3568d379142f921f59c4143ddaa14Duncan Sands bool Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII); 49874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert (Done && "Unable to resolve frame index!"); 4991f6a329f79b3568d379142f921f59c4143ddaa14Duncan Sands (void)Done; 50074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach} 50174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 50274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// saveScavengerRegister - Spill the register so it can be used by the 50374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// register scavenger. Return true. 50474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool 50574d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, 50674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineBasicBlock::iterator I, 50774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineBasicBlock::iterator &UseMI, 50874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const TargetRegisterClass *RC, 50974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned Reg) const { 51074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Thumb1 can't use the emergency spill slot on the stack because 51174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // ldr/str immediate offsets must be positive, and if we're referencing 51274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // off the frame pointer (if, for example, there are alloca() calls in 51374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // the function, the offset will be negative. Use R12 instead since that's 51474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // a call clobbered register that we know won't be used in Thumb1 mode. 51557148c166ab232191098492633c924fad9c44ef3Bill Wendling const TargetInstrInfo &TII = *MBB.getParent()->getTarget().getInstrInfo(); 51674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach DebugLoc DL; 5172a7b41ba4d3eb3c6003f6768dc20b28d83eac265Jim Grosbach AddDefaultPred(BuildMI(MBB, I, DL, TII.get(ARM::tMOVr)) 51863b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach .addReg(ARM::R12, RegState::Define) 51963b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach .addReg(Reg, RegState::Kill)); 52074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 52174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // The UseMI is where we would like to restore the register. If there's 52274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // interference with R12 before then, however, we'll need to restore it 52374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // before that instead and adjust the UseMI. 52474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach bool done = false; 52574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) { 52674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (II->isDebugValue()) 52774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach continue; 52874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // If this instruction affects R12, adjust our restore point. 52974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) { 53074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const MachineOperand &MO = II->getOperand(i); 531b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen if (MO.isRegMask() && MO.clobbersPhysReg(ARM::R12)) { 532b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen UseMI = II; 533b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen done = true; 534b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen break; 535b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen } 53674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (!MO.isReg() || MO.isUndef() || !MO.getReg() || 53774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach TargetRegisterInfo::isVirtualRegister(MO.getReg())) 53874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach continue; 53974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (MO.getReg() == ARM::R12) { 54074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach UseMI = II; 54174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach done = true; 54274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach break; 54374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 54474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 54574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 54674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Restore the register from R12 5472a7b41ba4d3eb3c6003f6768dc20b28d83eac265Jim Grosbach AddDefaultPred(BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVr)). 54863b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill)); 54974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 55074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 55174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach} 55274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 553fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbachvoid 55474d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 555108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier int SPAdj, unsigned FIOperandNum, 556108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier RegScavenger *RS) const { 55774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned VReg = 0; 55874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineInstr &MI = *II; 55974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineBasicBlock &MBB = *MI.getParent(); 56074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineFunction &MF = *MBB.getParent(); 56157148c166ab232191098492633c924fad9c44ef3Bill Wendling const ARMBaseInstrInfo &TII = 56257148c166ab232191098492633c924fad9c44ef3Bill Wendling *static_cast<const ARMBaseInstrInfo*>(MF.getTarget().getInstrInfo()); 56374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 56474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach DebugLoc dl = MI.getDebugLoc(); 56537a942cd52725b1d390989a8267a764b42fcb5d3Jakob Stoklund Olesen MachineInstrBuilder MIB(*MBB.getParent(), &MI); 56674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 56774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned FrameReg = ARM::SP; 568108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 56974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + 57074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MF.getFrameInfo()->getStackSize() + SPAdj; 57174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 572e53abc20724ddde4e91467671328b531361a734fTim Northover if (MF.getFrameInfo()->hasVarSizedObjects()) { 57316c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov assert(SPAdj == 0 && MF.getTarget().getFrameLowering()->hasFP(MF) && 5747920d96964d707a3af85332c98d95b2fabc3d5c9Benjamin Kramer "Unexpected"); 57574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // There are alloca()'s in this function, must reference off the frame 57665482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach // pointer or base pointer instead. 57765482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach if (!hasBasePointer(MF)) { 57865482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach FrameReg = getFrameRegister(MF); 57965482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach Offset -= AFI->getFramePtrSpillOffset(); 58065482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach } else 58165482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach FrameReg = BasePtr; 58274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 58374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 5840f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen // PEI::scavengeFrameVirtualRegs() cannot accurately track SPAdj because the 5850f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen // call frame setup/destroy instructions have already been eliminated. That 5860f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen // means the stack pointer cannot be used to access the emergency spill slot 5870f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen // when !hasReservedCallFrame(). 5880f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen#ifndef NDEBUG 589dc3beb90178fc316f63790812b22201884eaa017Hal Finkel if (RS && FrameReg == ARM::SP && RS->isScavengingFrameIndex(FrameIndex)){ 5900f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen assert(MF.getTarget().getFrameLowering()->hasReservedCallFrame(MF) && 5910f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen "Cannot use SP to access the emergency spill slot in " 5920f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen "functions without a reserved call frame"); 5930f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen assert(!MF.getFrameInfo()->hasVarSizedObjects() && 5940f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen "Cannot use SP to access the emergency spill slot in " 5950f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen "functions with variable sized frame objects"); 5960f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen } 5970f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen#endif // NDEBUG 5980f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen 59974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Special handling of dbg_value instructions. 60074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (MI.isDebugValue()) { 601108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier MI.getOperand(FIOperandNum). ChangeToRegister(FrameReg, false /*isDef*/); 602108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset); 603fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach return; 60474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 60574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 60674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Modify MI as necessary to handle as much of 'Offset' as possible 60774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert(AFI->isThumbFunction() && 60874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach "This eliminateFrameIndex only supports Thumb1!"); 609108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier if (rewriteFrameIndex(MI, FIOperandNum, FrameReg, Offset, TII)) 610fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach return; 611a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 612a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If we get here, the immediate doesn't fit into the instruction. We folded 613a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // as much as possible above, handle the rest, providing a register that is 614a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // SP+LargeImm. 615a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(Offset && "This code isn't needed if offset already handled!"); 616a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 61774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned Opcode = MI.getOpcode(); 61874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 619446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng // Remove predicate first. 620446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng int PIdx = MI.findFirstPredOperandIdx(); 621446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (PIdx != -1) 622446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng removeOperands(MI, PIdx); 623446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 6245a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng if (MI.mayLoad()) { 625a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Use the destination register to materialize sp + offset. 626a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned TmpReg = MI.getOperand(0).getReg(); 627a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool UseRR = false; 62874472b4bf963c424da04f42dffdb94c85ef964bcJim Grosbach if (Opcode == ARM::tLDRspi) { 629a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (FrameReg == ARM::SP) 6303daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg, 6313daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov Offset, false, TII, *this); 632a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 633378445303b10b092a898a75131141a8259cff50bEvan Cheng emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset); 634a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov UseRR = true; 635a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 636446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 63757caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII, 63857caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov *this); 639446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 640446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 6416e90ce21cc2b0627ee9219e3fb0cf808f2b73328Eric Christopher MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi)); 642108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier MI.getOperand(FIOperandNum).ChangeToRegister(TmpReg, false, false, true); 643a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (UseRR) 6445f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame 6455f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach // register. The offset is already handled in the vreg value. 646108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false, 647108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier false); 6485a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng } else if (MI.mayStore()) { 649420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper VReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass); 6503d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach bool UseRR = false; 651b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach 65274472b4bf963c424da04f42dffdb94c85ef964bcJim Grosbach if (Opcode == ARM::tSTRspi) { 6533d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach if (FrameReg == ARM::SP) 6543daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg, 6553daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov Offset, false, TII, *this); 6563d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach else { 657b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach emitLoadConstPool(MBB, II, dl, VReg, 0, Offset); 6583d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach UseRR = true; 6593d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach } 6603d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach } else 66157caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII, 66257caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov *this); 6636e90ce21cc2b0627ee9219e3fb0cf808f2b73328Eric Christopher MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi)); 664108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier MI.getOperand(FIOperandNum).ChangeToRegister(VReg, false, false, true); 6655f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach if (UseRR) 6665f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame 6675f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach // register. The offset is already handled in the vreg value. 668108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false, 669108fb3202af6f500073cdbb7be32c25d7a273a2eChad Rosier false); 670f4caf69720d807573c50d41aa06bcec1c99bdbbdBill Wendling } else { 671bc2198133a1836598b54b943420748e75d5dea94Craig Topper llvm_unreachable("Unexpected opcode!"); 672f4caf69720d807573c50d41aa06bcec1c99bdbbdBill Wendling } 673446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 674446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng // Add predicate back if it's needed. 67537a942cd52725b1d390989a8267a764b42fcb5d3Jakob Stoklund Olesen if (MI.isPredicable()) 676446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng AddDefaultPred(MIB); 677a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 678