Thumb1RegisterInfo.cpp revision 420761a0f193e87d08ee1c51b26bba23ab4bac7f
131d157ae1ac2cd9c787dc3c1d28e64c682803844Jia Liu//===-- Thumb1RegisterInfo.cpp - Thumb-1 Register Information -------------===// 2a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 3a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// The LLVM Compiler Infrastructure 4a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 5a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// This file is distributed under the University of Illinois Open Source 6a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// License. See LICENSE.TXT for details. 7a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 8a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//===----------------------------------------------------------------------===// 9a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 1031c24bf5b39cc8391d4cfdbf8cf5163975fdb81eJim Grosbach// This file contains the Thumb-1 implementation of the TargetRegisterInfo 1131c24bf5b39cc8391d4cfdbf8cf5163975fdb81eJim Grosbach// class. 12a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 13a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//===----------------------------------------------------------------------===// 14a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 15c1f6f42049696e7357fb4837e1b25dabbaed3fe6Craig Topper#include "Thumb1RegisterInfo.h" 16a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARM.h" 1777521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin#include "ARMBaseInstrInfo.h" 18a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMMachineFunctionInfo.h" 19a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMSubtarget.h" 20ee04a6d3a40c3017124e3fd89a0db473a2824498Evan Cheng#include "MCTargetDesc/ARMAddressingModes.h" 21a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/Constants.h" 22a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/DerivedTypes.h" 239adc0abad3c3ed40a268ccbcee0c74cb9e1359feOwen Anderson#include "llvm/Function.h" 249adc0abad3c3ed40a268ccbcee0c74cb9e1359feOwen Anderson#include "llvm/LLVMContext.h" 25a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineConstantPool.h" 26a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineFrameInfo.h" 27a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineFunction.h" 28a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineInstrBuilder.h" 29a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineRegisterInfo.h" 300f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen#include "llvm/CodeGen/RegisterScavenging.h" 3116c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov#include "llvm/Target/TargetFrameLowering.h" 32a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/Target/TargetMachine.h" 334e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach#include "llvm/Support/CommandLine.h" 34ab7c09b6b6f4516a631fd6788918c237c83939afTorok Edwin#include "llvm/Support/ErrorHandling.h" 35dac237e18209b697a8ba122d0ddd9cad4dfba1f8Torok Edwin#include "llvm/Support/raw_ostream.h" 36a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 378c407d45964fbba19719be555324f247e4fb14e1Dan Gohmannamespace llvm { 384e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbachextern cl::opt<bool> ReuseFrameIndexVals; 398c407d45964fbba19719be555324f247e4fb14e1Dan Gohman} 408c407d45964fbba19719be555324f247e4fb14e1Dan Gohman 418c407d45964fbba19719be555324f247e4fb14e1Dan Gohmanusing namespace llvm; 424e501545cd12d903d35096f42eb5fdbe4603d5daJim Grosbach 43db5a71a8e01ed9a0d93a19176df6ea0aea510d7bDavid GoodwinThumb1RegisterInfo::Thumb1RegisterInfo(const ARMBaseInstrInfo &tii, 44b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const ARMSubtarget &sti) 45a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov : ARMBaseRegisterInfo(tii, sti) { 46a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 47a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 48c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesenconst TargetRegisterClass* 49c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund OlesenThumb1RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) 50c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen const { 51fa226bccaa90c520cac154df74069bbabb976eabJakob Stoklund Olesen if (ARM::tGPRRegClass.hasSubClassEq(RC)) 52420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper return &ARM::tGPRRegClass; 53c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC); 54c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen} 55c9e5015dece0a1a73bec358e11bc87594831279dJakob Stoklund Olesen 561db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesenconst TargetRegisterClass * 571db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund OlesenThumb1RegisterInfo::getPointerRegClass(unsigned Kind) const { 58420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper return &ARM::tGPRRegClass; 591db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesen} 601db952d0c6c93f24619af5de2ea1b0550665479cJakob Stoklund Olesen 61a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitLoadConstPool - Emits a load from constpool to materialize the 62a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// specified immediate. 633daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikovvoid 643daccd82d3151fa3629de430b55698a81084fc9eAnton KorobeynikovThumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, 653daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 663daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov DebugLoc dl, 673daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov unsigned DestReg, unsigned SubIdx, 683daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov int Val, 693daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov ARMCC::CondCodes Pred, unsigned PredReg, 703daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov unsigned MIFlags) const { 71a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFunction &MF = *MBB.getParent(); 72a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineConstantPool *ConstantPool = MF.getConstantPool(); 7346510a73e977273ec67747eb34cbdb43f815e451Dan Gohman const Constant *C = ConstantInt::get( 741d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val); 75a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); 76a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 773e333637f172c30adf5c8333b592fbde17ff9f78Jim Grosbach BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRpci)) 78b3fcc06d2124f9d01e3b48097b44cc141309908eAnton Korobeynikov .addReg(DestReg, getDefRegState(true), SubIdx) 79b3fcc06d2124f9d01e3b48097b44cc141309908eAnton Korobeynikov .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg) 80b3fcc06d2124f9d01e3b48097b44cc141309908eAnton Korobeynikov .setMIFlags(MIFlags); 81a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 82a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 83446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 84a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize 85a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// a destreg = basereg + immediate in Thumb code. Materialize the immediate 86a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// in a register using mov / mvn sequences or load the immediate from a 87a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constpool entry. 88a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic 89a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovvoid emitThumbRegPlusImmInReg(MachineBasicBlock &MBB, 90a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 913daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov DebugLoc dl, 92a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg, unsigned BaseReg, 93a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int NumBytes, bool CanChangeCC, 94a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrInfo &TII, 95e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach const ARMBaseRegisterInfo& MRI, 963daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov unsigned MIFlags = MachineInstr::NoFlags) { 973d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach MachineFunction &MF = *MBB.getParent(); 9855ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov bool isHigh = !isARMLowRegister(DestReg) || 9955ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov (BaseReg != 0 && !isARMLowRegister(BaseReg)); 100a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = false; 101a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Subtract doesn't have high register version. Load the negative value 102a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // if either base or dest register is a high register. Also, if do not 103a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // issue sub as part of the sequence if condition register is to be 104a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // preserved. 105a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes < 0 && !isHigh && CanChangeCC) { 106a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isSub = true; 107a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = -NumBytes; 108a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 109a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned LdReg = DestReg; 110a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == ARM::SP) { 111a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(BaseReg == ARM::SP && "Unexpected!"); 112420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper LdReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass); 113a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 114a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 115a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes <= 255 && NumBytes >= 0) 116b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) 1173daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .addImm(NumBytes).setMIFlags(MIFlags); 118a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else if (NumBytes < 0 && NumBytes >= -255) { 119b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) 1203daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .addImm(NumBytes).setMIFlags(MIFlags); 121b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg)) 1223daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .addReg(LdReg, RegState::Kill).setMIFlags(MIFlags); 123a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else 1243daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes, 1253daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov ARMCC::AL, 0, MIFlags); 126a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 127a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Emit add / sub. 128a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr); 129446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB = 130446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); 131446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (Opc != ARM::tADDhirr) 132b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng MIB = AddDefaultT1CC(MIB); 133a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == ARM::SP || isSub) 134a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill); 135a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else 136a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill); 137446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng AddDefaultPred(MIB); 138a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 139a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 140a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// calcNumMI - Returns the number of instructions required to materialize 141a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// the specific add / sub r, c instruction. 142a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic unsigned calcNumMI(int Opc, int ExtraOpc, unsigned Bytes, 143a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits, unsigned Scale) { 144a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = 0; 145a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = ((1 << NumBits) - 1) * Scale; 146a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 147a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::tADDrSPi) { 148a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 149a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 150a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs++; 151a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 152a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 1; // Followed by a number of tADDi8. 153a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Chunk = ((1 << NumBits) - 1) * Scale; 154a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 155a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 156a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs += Bytes / Chunk; 157a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if ((Bytes % Chunk) != 0) 158a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs++; 159a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (ExtraOpc) 160a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs++; 161a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return NumMIs; 162a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 163a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 164a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize 165a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// a destreg = basereg + immediate in Thumb code. 166e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbachvoid llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, 167e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach MachineBasicBlock::iterator &MBBI, 16857caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov DebugLoc dl, 169e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach unsigned DestReg, unsigned BaseReg, 170e4ad387a5a88dae20f0f7578e55170bbc8eee2a9Jim Grosbach int NumBytes, const TargetInstrInfo &TII, 1713daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov const ARMBaseRegisterInfo& MRI, 1723daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov unsigned MIFlags) { 173a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = NumBytes < 0; 174a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Bytes = (unsigned)NumBytes; 175a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (isSub) Bytes = -NumBytes; 176a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isMul4 = (Bytes & 3) == 0; 177a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isTwoAddr = false; 178a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool DstNotEqBase = false; 179a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits = 1; 180a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Scale = 1; 181a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Opc = 0; 182a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ExtraOpc = 0; 183446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng bool NeedCC = false; 184a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 185a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == BaseReg && BaseReg == ARM::SP) { 186a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); 187a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 7; 188a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 189a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; 190a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isTwoAddr = true; 191a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else if (!isSub && BaseReg == ARM::SP) { 192a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add sp, 403 193a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // => 194a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add sp, 100 * 4 195a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add r1, 3 196a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!isMul4) { 197a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes &= ~3; 198a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ExtraOpc = ARM::tADDi3; 199a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 200a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 201a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 202a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = ARM::tADDrSPi; 203a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 204a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // sp = sub sp, c 205a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = sub sp, c 206a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r8 = sub sp, c 207a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg != BaseReg) 208a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DstNotEqBase = true; 209a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 210f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng if (DestReg == ARM::SP) { 211f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; 212f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); 213f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng NumBits = 7; 214f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Scale = 4; 215f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng } else { 216f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; 217f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng NumBits = 8; 2185b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach NeedCC = true; 219f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng } 220a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isTwoAddr = true; 221a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 222a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 223a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale); 224a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2; 225a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumMIs > Threshold) { 226a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // This will expand into too many instructions. Load the immediate from a 227a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // constpool entry. 2283daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, MBBI, dl, 2293daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov DestReg, BaseReg, NumBytes, true, 2303daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov TII, MRI, MIFlags); 231a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return; 232a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 233a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 234a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DstNotEqBase) { 23555ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov if (isARMLowRegister(DestReg) && isARMLowRegister(BaseReg)) { 236a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If both are low registers, emit DestReg = add BaseReg, max(Imm, 7) 237a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = (1 << 3) - 1; 238a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 239a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 240e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng const MCInstrDesc &MCID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); 241446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng const MachineInstrBuilder MIB = 2424372ca6fe4119d708d43d9c9ac3feafc7607952aJim Grosbach AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg) 2434372ca6fe4119d708d43d9c9ac3feafc7607952aJim Grosbach .setMIFlags(MIFlags)); 244446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal)); 245a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 24663b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) 24763b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach .addReg(BaseReg, RegState::Kill)) 2483daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .setMIFlags(MIFlags); 249a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 250a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BaseReg = DestReg; 251a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 252a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 253a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = ((1 << NumBits) - 1) * Scale; 254a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov while (Bytes) { 255a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 256a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 257a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ThisVal /= Scale; 258a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Build the new tADD / tSUB. 259446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (isTwoAddr) { 260446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); 261446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedCC) 262b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng MIB = AddDefaultT1CC(MIB); 2633daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov MIB.addReg(DestReg).addImm(ThisVal); 2645b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach MIB = AddDefaultPred(MIB); 2653daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov MIB.setMIFlags(MIFlags); 2668884148b8e8f19d5484e735618cf188cfa02c626Jim Grosbach } else { 267a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isKill = BaseReg != ARM::SP; 268446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); 269446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (NeedCC) 270b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng MIB = AddDefaultT1CC(MIB); 271446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal); 2725b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach MIB = AddDefaultPred(MIB); 2733daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov MIB.setMIFlags(MIFlags); 274a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 2753daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov BaseReg = DestReg; 276a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::tADDrSPi) { 277a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r4 = add sp, imm 278a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r4 = add r4, imm 279a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ... 280a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 281a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 1; 282a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Chunk = ((1 << NumBits) - 1) * Scale; 283a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; 2845b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach NeedCC = isTwoAddr = true; 285a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 286a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 287a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 288a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 289446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (ExtraOpc) { 290e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng const MCInstrDesc &MCID = TII.get(ExtraOpc); 291e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)) 292446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addReg(DestReg, RegState::Kill) 2933daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .addImm(((unsigned)NumBytes) & 3) 2943daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov .setMIFlags(MIFlags)); 295446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 296a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 297a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 29855ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikovstatic void emitSPUpdate(MachineBasicBlock &MBB, 29955ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov MachineBasicBlock::iterator &MBBI, 30055ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov const TargetInstrInfo &TII, DebugLoc dl, 301b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo &MRI, 30255ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov int NumBytes) { 30357caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, TII, 30457caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov MRI); 305a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 306a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 307b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo:: 308a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton KorobeynikoveliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 309a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator I) const { 31016c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 311d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov 312d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov if (!TFI->hasReservedCallFrame(MF)) { 313a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If we have alloca, convert as follows: 314a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ADJCALLSTACKDOWN -> sub, sp, sp, amount 315a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ADJCALLSTACKUP -> add, sp, sp, amount 316a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineInstr *Old = I; 317a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = Old->getDebugLoc(); 318a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Amount = Old->getOperand(0).getImm(); 319a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Amount != 0) { 320a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // We need to keep the stack aligned properly. To do this, we round the 321a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // amount of space needed for the outgoing arguments up to the next 322a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // alignment boundary. 32316c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov unsigned Align = TFI->getStackAlignment(); 324a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Amount = (Amount+Align-1)/Align*Align; 325a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 326a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Replace the pseudo instruction with a new instruction... 327a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Opc = Old->getOpcode(); 328a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) { 32955ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, I, TII, dl, *this, -Amount); 330a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 331a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP); 33255ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, I, TII, dl, *this, Amount); 333a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 334a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 335a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 336a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBB.erase(I); 337a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 338a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 339a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbConstant - Emit a series of instructions to materialize a 340a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constant. 341a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic void emitThumbConstant(MachineBasicBlock &MBB, 342a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 343a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg, int Imm, 344a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrInfo &TII, 345b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo& MRI, 346a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl) { 347a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = Imm < 0; 348a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (isSub) Imm = -Imm; 349a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 350a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Chunk = (1 << 8) - 1; 351a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ThisVal = (Imm > Chunk) ? Chunk : Imm; 352a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Imm -= ThisVal; 353b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), 354b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng DestReg)) 355446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addImm(ThisVal)); 356a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Imm > 0) 35757caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, dl, DestReg, DestReg, Imm, TII, MRI); 358446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (isSub) { 359e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng const MCInstrDesc &MCID = TII.get(ARM::tRSB); 360e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)) 361446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng .addReg(DestReg, RegState::Kill)); 362446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 363446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng} 364446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 365446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Chengstatic void removeOperands(MachineInstr &MI, unsigned i) { 366446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng unsigned Op = i; 367446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng for (unsigned e = MI.getNumOperands(); i != e; ++i) 368446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MI.RemoveOperand(Op); 369a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 370a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 3717a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling/// convertToNonSPOpcode - Change the opcode to the non-SP version, because 3727a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling/// we're replacing the frame index with a non-SP register. 3737a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendlingstatic unsigned convertToNonSPOpcode(unsigned Opcode) { 3747a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling switch (Opcode) { 3757a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling case ARM::tLDRspi: 3767a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling return ARM::tLDRi; 3777a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 3787a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling case ARM::tSTRspi: 3797a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling return ARM::tSTRi; 3807a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling } 3817a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 3827a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling return Opcode; 3837a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling} 3847a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 38574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool Thumb1RegisterInfo:: 38674d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachrewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, 38774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned FrameReg, int &Offset, 38874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const ARMBaseInstrInfo &TII) const { 389a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineInstr &MI = *II; 390a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock &MBB = *MI.getParent(); 391a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = MI.getDebugLoc(); 392a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Opcode = MI.getOpcode(); 393e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng const MCInstrDesc &Desc = MI.getDesc(); 394a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); 395a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 396a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opcode == ARM::tADDrSPi) { 39774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach Offset += MI.getOperand(FrameRegIdx+1).getImm(); 398a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 399a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Can't use tADDrSPi if it's based off the frame pointer. 400a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits = 0; 401a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Scale = 1; 402a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (FrameReg != ARM::SP) { 403a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opcode = ARM::tADDi3; 404a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 3; 405a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 406a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 407a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 408a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert((Offset & 3) == 0 && 409a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov "Thumb add/sub sp, #imm immediate must be multiple of 4!"); 410a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 411a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 41235f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen unsigned PredReg; 41335f0febcb66b5a50a5a750efcbefc95f7fc25c7bJakob Stoklund Olesen if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) { 414a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Turn it into a move. 4152a7b41ba4d3eb3c6003f6768dc20b28d83eac265Jim Grosbach MI.setDesc(TII.get(ARM::tMOVr)); 41674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 4175b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach // Remove offset 41863b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach MI.RemoveOperand(FrameRegIdx+1); 41963b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach MachineInstrBuilder MIB(&MI); 42074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 421a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 422a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 423a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Common case: small offset, fits into instruction. 424a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Mask = (1 << NumBits) - 1; 425a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (((Offset / Scale) & ~Mask) == 0) { 426a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Replace the FrameIndex with sp / fp 427446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (Opcode == ARM::tADDi3) { 4285b81584f7403ffdb9cc6babaaeb0411c080e0f81Jim Grosbach MI.setDesc(TII.get(Opcode)); 42974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach removeOperands(MI, FrameRegIdx); 430446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB(&MI); 431b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg) 432f6fe9579505be86420beea04f2c9ecb0fd7c55fdEvan Cheng .addImm(Offset / Scale)); 433446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 43474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 43574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset / Scale); 436446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 43774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 438a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 439a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 440a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg = MI.getOperand(0).getReg(); 441a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Bytes = (Offset > 0) ? Offset : -Offset; 442a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = calcNumMI(Opcode, 0, Bytes, NumBits, Scale); 443a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // MI would expand into a large number of instructions. Don't try to 444a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // simplify the immediate. 445a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumMIs > 2) { 44657caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII, 44757caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov *this); 448a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBB.erase(II); 44974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 450a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 451a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 452a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Offset > 0) { 453a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Translate r0 = add sp, imm to 454a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add sp, 255*4 455a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add r0, (imm - 255*4) 456446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (Opcode == ARM::tADDi3) { 45729b9d7e4ea7521be25bccdb66ecd9c9df5ed8b4bChad Rosier MI.setDesc(TII.get(Opcode)); 45874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach removeOperands(MI, FrameRegIdx); 459446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB(&MI); 460b46aaa3874d2753632c48400c66be1a10ac18d42Evan Cheng AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg).addImm(Mask)); 461446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 46274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 46374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Mask); 464446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 465a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset = (Offset - Mask * Scale); 4667896c9f436a4eda5ec15e882a7505ba482a2fcd0Chris Lattner MachineBasicBlock::iterator NII = llvm::next(II); 46757caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, NII, dl, DestReg, DestReg, Offset, TII, 46857caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov *this); 469a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 470a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Translate r0 = add sp, -imm to 471a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = -imm (this is then translated into a series of instructons) 472a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add r0, sp 473a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbConstant(MBB, II, DestReg, Offset, TII, *this, dl); 474bae20a6353583089224b94280a2dd69805dca247Evan Cheng 475a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.setDesc(TII.get(ARM::tADDhirr)); 47674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false, false, true); 47774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx+1).ChangeToRegister(FrameReg, false); 478a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 47974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 480a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 4817a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling if (AddrMode != ARMII::AddrModeT1_s) 482c23197a26f34f559ea9797de51e187087c039c42Torok Edwin llvm_unreachable("Unsupported addressing mode!"); 4837a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 4847a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling unsigned ImmIdx = FrameRegIdx + 1; 4857a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling int InstrOffs = MI.getOperand(ImmIdx).getImm(); 4867a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5; 4877a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling unsigned Scale = 4; 488a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 489a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset += InstrOffs * Scale; 4907a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!"); 491a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 492a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Common case: small offset, fits into instruction. 493a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineOperand &ImmOp = MI.getOperand(ImmIdx); 494a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ImmedOffset = Offset / Scale; 495a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Mask = (1 << NumBits) - 1; 4967a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 497a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if ((unsigned)Offset <= Mask * Scale) { 4987a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling // Replace the FrameIndex with the frame register (e.g., sp). 49974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); 500a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(ImmedOffset); 5017a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 5027a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling // If we're using a register where sp was stored, convert the instruction 5037a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling // to the non-SP version. 5047a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling unsigned NewOpc = convertToNonSPOpcode(Opcode); 5057a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling if (NewOpc != Opcode && FrameReg != ARM::SP) 5067a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling MI.setDesc(TII.get(NewOpc)); 5077a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 50874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 509a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 510a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 5117a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling NumBits = 5; 5127a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling Mask = (1 << NumBits) - 1; 5137a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 514a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If this is a thumb spill / restore, we will be using a constpool load to 515a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // materialize the offset. 51674472b4bf963c424da04f42dffdb94c85ef964bcJim Grosbach if (Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) { 517a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(0); 5187a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling } else { 519a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Otherwise, it didn't fit. Pull in what we can to simplify the immed. 520a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmedOffset = ImmedOffset & Mask; 521a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(ImmedOffset); 5227a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling Offset &= ~(Mask * Scale); 523a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 524a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 5257a905a82f7425d1a10b828c8bb3365b2ebc15833Bill Wendling 52674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return Offset == 0; 52774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach} 52874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 52974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachvoid 53074d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I, 53174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned BaseReg, int64_t Offset) const { 53274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineInstr &MI = *I; 53374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach int Off = Offset; // ARM doesn't need the general 64-bit offsets 53474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned i = 0; 53574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 53674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach while (!MI.getOperand(i).isFI()) { 53774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach ++i; 53874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 53974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 5401f6a329f79b3568d379142f921f59c4143ddaa14Duncan Sands bool Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII); 54174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert (Done && "Unable to resolve frame index!"); 5421f6a329f79b3568d379142f921f59c4143ddaa14Duncan Sands (void)Done; 54374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach} 54474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 54574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// saveScavengerRegister - Spill the register so it can be used by the 54674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach/// register scavenger. Return true. 54774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbachbool 54874d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, 54974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineBasicBlock::iterator I, 55074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineBasicBlock::iterator &UseMI, 55174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const TargetRegisterClass *RC, 55274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned Reg) const { 55374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Thumb1 can't use the emergency spill slot on the stack because 55474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // ldr/str immediate offsets must be positive, and if we're referencing 55574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // off the frame pointer (if, for example, there are alloca() calls in 55674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // the function, the offset will be negative. Use R12 instead since that's 55774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // a call clobbered register that we know won't be used in Thumb1 mode. 55874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach DebugLoc DL; 5592a7b41ba4d3eb3c6003f6768dc20b28d83eac265Jim Grosbach AddDefaultPred(BuildMI(MBB, I, DL, TII.get(ARM::tMOVr)) 56063b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach .addReg(ARM::R12, RegState::Define) 56163b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach .addReg(Reg, RegState::Kill)); 56274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 56374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // The UseMI is where we would like to restore the register. If there's 56474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // interference with R12 before then, however, we'll need to restore it 56574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // before that instead and adjust the UseMI. 56674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach bool done = false; 56774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) { 56874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (II->isDebugValue()) 56974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach continue; 57074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // If this instruction affects R12, adjust our restore point. 57174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) { 57274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach const MachineOperand &MO = II->getOperand(i); 573b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen if (MO.isRegMask() && MO.clobbersPhysReg(ARM::R12)) { 574b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen UseMI = II; 575b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen done = true; 576b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen break; 577b24b820bd7ddfe118141422f4d0cf378b2c9a6fdJakob Stoklund Olesen } 57874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (!MO.isReg() || MO.isUndef() || !MO.getReg() || 57974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach TargetRegisterInfo::isVirtualRegister(MO.getReg())) 58074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach continue; 58174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (MO.getReg() == ARM::R12) { 58274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach UseMI = II; 58374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach done = true; 58474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach break; 58574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 58674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 58774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 58874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Restore the register from R12 5892a7b41ba4d3eb3c6003f6768dc20b28d83eac265Jim Grosbach AddDefaultPred(BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVr)). 59063b46faeb8acae9b7e5f865b7417dc00b9b9dad3Jim Grosbach addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill)); 59174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 59274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach return true; 59374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach} 59474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 595fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbachvoid 59674d7b0af58951dce2f874c600a6a48a2454b4914Jim GrosbachThumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 597fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach int SPAdj, RegScavenger *RS) const { 59874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned VReg = 0; 59974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned i = 0; 60074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineInstr &MI = *II; 60174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineBasicBlock &MBB = *MI.getParent(); 60274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MachineFunction &MF = *MBB.getParent(); 60374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 60474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach DebugLoc dl = MI.getDebugLoc(); 60574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 60674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach while (!MI.getOperand(i).isFI()) { 60774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach ++i; 60874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 60974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 61074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 61174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned FrameReg = ARM::SP; 61274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach int FrameIndex = MI.getOperand(i).getIndex(); 61374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + 61474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MF.getFrameInfo()->getStackSize() + SPAdj; 61574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 616ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach if (AFI->isGPRCalleeSavedArea1Frame(FrameIndex)) 617ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach Offset -= AFI->getGPRCalleeSavedArea1Offset(); 618ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach else if (AFI->isGPRCalleeSavedArea2Frame(FrameIndex)) 619ab3d00e5350fd4c097e2a5b077da7584692029a7Jim Grosbach Offset -= AFI->getGPRCalleeSavedArea2Offset(); 62074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach else if (MF.getFrameInfo()->hasVarSizedObjects()) { 62116c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov assert(SPAdj == 0 && MF.getTarget().getFrameLowering()->hasFP(MF) && 6227920d96964d707a3af85332c98d95b2fabc3d5c9Benjamin Kramer "Unexpected"); 62374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // There are alloca()'s in this function, must reference off the frame 62465482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach // pointer or base pointer instead. 62565482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach if (!hasBasePointer(MF)) { 62665482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach FrameReg = getFrameRegister(MF); 62765482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach Offset -= AFI->getFramePtrSpillOffset(); 62865482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach } else 62965482b1bb873dd820f54a24a2f34bd65f2669e5cJim Grosbach FrameReg = BasePtr; 63074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 63174d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 6320f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen // PEI::scavengeFrameVirtualRegs() cannot accurately track SPAdj because the 6330f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen // call frame setup/destroy instructions have already been eliminated. That 6340f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen // means the stack pointer cannot be used to access the emergency spill slot 6350f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen // when !hasReservedCallFrame(). 6360f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen#ifndef NDEBUG 6370f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen if (RS && FrameReg == ARM::SP && FrameIndex == RS->getScavengingFrameIndex()){ 6380f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen assert(MF.getTarget().getFrameLowering()->hasReservedCallFrame(MF) && 6390f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen "Cannot use SP to access the emergency spill slot in " 6400f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen "functions without a reserved call frame"); 6410f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen assert(!MF.getFrameInfo()->hasVarSizedObjects() && 6420f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen "Cannot use SP to access the emergency spill slot in " 6430f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen "functions with variable sized frame objects"); 6440f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen } 6450f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen#endif // NDEBUG 6460f9d07fb2526c0acdf7ad9fa6e9c1a97a746c0e9Jakob Stoklund Olesen 64774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Special handling of dbg_value instructions. 64874d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (MI.isDebugValue()) { 64974d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(i). ChangeToRegister(FrameReg, false /*isDef*/); 65074d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach MI.getOperand(i+1).ChangeToImmediate(Offset); 651fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach return; 65274d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach } 65374d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 65474d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach // Modify MI as necessary to handle as much of 'Offset' as possible 65574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach assert(AFI->isThumbFunction() && 65674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach "This eliminateFrameIndex only supports Thumb1!"); 65774d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach if (rewriteFrameIndex(MI, i, FrameReg, Offset, TII)) 658fcb4a8ead3cd8d9540d5eaa448af5d14a0ee341aJim Grosbach return; 659a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 660a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If we get here, the immediate doesn't fit into the instruction. We folded 661a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // as much as possible above, handle the rest, providing a register that is 662a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // SP+LargeImm. 663a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(Offset && "This code isn't needed if offset already handled!"); 664a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 66574d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach unsigned Opcode = MI.getOpcode(); 66674d7b0af58951dce2f874c600a6a48a2454b4914Jim Grosbach 667446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng // Remove predicate first. 668446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng int PIdx = MI.findFirstPredOperandIdx(); 669446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng if (PIdx != -1) 670446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng removeOperands(MI, PIdx); 671446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 6725a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng if (MI.mayLoad()) { 673a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Use the destination register to materialize sp + offset. 674a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned TmpReg = MI.getOperand(0).getReg(); 675a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool UseRR = false; 67674472b4bf963c424da04f42dffdb94c85ef964bcJim Grosbach if (Opcode == ARM::tLDRspi) { 677a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (FrameReg == ARM::SP) 6783daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg, 6793daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov Offset, false, TII, *this); 680a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 681378445303b10b092a898a75131141a8259cff50bEvan Cheng emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset); 682a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov UseRR = true; 683a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 684446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } else { 68557caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII, 68657caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov *this); 687446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 688446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 6896e90ce21cc2b0627ee9219e3fb0cf808f2b73328Eric Christopher MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi)); 690a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(TmpReg, false, false, true); 691a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (UseRR) 6925f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame 6935f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach // register. The offset is already handled in the vreg value. 6945f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach MI.getOperand(i+1).ChangeToRegister(FrameReg, false, false, false); 6955a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng } else if (MI.mayStore()) { 696420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper VReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass); 6973d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach bool UseRR = false; 698b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach 69974472b4bf963c424da04f42dffdb94c85ef964bcJim Grosbach if (Opcode == ARM::tSTRspi) { 7003d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach if (FrameReg == ARM::SP) 7013daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg, 7023daccd82d3151fa3629de430b55698a81084fc9eAnton Korobeynikov Offset, false, TII, *this); 7033d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach else { 704b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach emitLoadConstPool(MBB, II, dl, VReg, 0, Offset); 7053d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach UseRR = true; 7063d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach } 7073d6cb88a64fe67064de206405951eb326d86fc0cJim Grosbach } else 70857caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII, 70957caad7a33ff145b71545f10dcfbbf2fd0f595d3Anton Korobeynikov *this); 7106e90ce21cc2b0627ee9219e3fb0cf808f2b73328Eric Christopher MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi)); 711b58f498f7502e7e1833decbbbb4df771367c7341Jim Grosbach MI.getOperand(i).ChangeToRegister(VReg, false, false, true); 7125f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach if (UseRR) 7135f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame 7145f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach // register. The offset is already handled in the vreg value. 7155f3e2be7c941b26ac865fa00c3f314bcd1e6cec8Jim Grosbach MI.getOperand(i+1).ChangeToRegister(FrameReg, false, false, false); 716f4caf69720d807573c50d41aa06bcec1c99bdbbdBill Wendling } else { 717bc2198133a1836598b54b943420748e75d5dea94Craig Topper llvm_unreachable("Unexpected opcode!"); 718f4caf69720d807573c50d41aa06bcec1c99bdbbdBill Wendling } 719446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng 720446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng // Add predicate back if it's needed. 7215a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng if (MI.isPredicable()) { 722446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng MachineInstrBuilder MIB(&MI); 723446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng AddDefaultPred(MIB); 724446c428bf394b7113b0f18cbacb5e87b4efd1e14Evan Cheng } 725a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 726