1e580952dSDimitry Andric //===- LocalStackSlotAllocation.cpp - Pre-allocate locals to stack slots --===// 2e580952dSDimitry Andric // 3e580952dSDimitry Andric // The LLVM Compiler Infrastructure 4e580952dSDimitry Andric // 5e580952dSDimitry Andric // This file is distributed under the University of Illinois Open Source 6e580952dSDimitry Andric // License. See LICENSE.TXT for details. 7e580952dSDimitry Andric // 8e580952dSDimitry Andric //===----------------------------------------------------------------------===// 9e580952dSDimitry Andric // 10e580952dSDimitry Andric // This pass assigns local frame indices to stack slots relative to one another 11e580952dSDimitry Andric // and allocates additional base registers to access them when the target 122754fe60SDimitry Andric // estimates they are likely to be out of range of stack pointer and frame 13e580952dSDimitry Andric // pointer relative addressing. 14e580952dSDimitry Andric // 15e580952dSDimitry Andric //===----------------------------------------------------------------------===// 16e580952dSDimitry Andric 17e580952dSDimitry Andric #define DEBUG_TYPE "localstackalloc" 18e580952dSDimitry Andric #include "llvm/Constants.h" 19e580952dSDimitry Andric #include "llvm/DerivedTypes.h" 20e580952dSDimitry Andric #include "llvm/Instructions.h" 21e580952dSDimitry Andric #include "llvm/Intrinsics.h" 22e580952dSDimitry Andric #include "llvm/LLVMContext.h" 23e580952dSDimitry Andric #include "llvm/Module.h" 24e580952dSDimitry Andric #include "llvm/Pass.h" 25e580952dSDimitry Andric #include "llvm/ADT/SmallSet.h" 26e580952dSDimitry Andric #include "llvm/ADT/Statistic.h" 27e580952dSDimitry Andric #include "llvm/ADT/STLExtras.h" 28e580952dSDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 29e580952dSDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 30e580952dSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 31e580952dSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 32e580952dSDimitry Andric #include "llvm/CodeGen/Passes.h" 33e580952dSDimitry Andric #include "llvm/Support/Debug.h" 34e580952dSDimitry Andric #include "llvm/Support/ErrorHandling.h" 35e580952dSDimitry Andric #include "llvm/Support/raw_ostream.h" 36e580952dSDimitry Andric #include "llvm/Target/TargetRegisterInfo.h" 372754fe60SDimitry Andric #include "llvm/Target/TargetFrameLowering.h" 38e580952dSDimitry Andric 39e580952dSDimitry Andric using namespace llvm; 40e580952dSDimitry Andric 41e580952dSDimitry Andric STATISTIC(NumAllocations, "Number of frame indices allocated into local block"); 42e580952dSDimitry Andric STATISTIC(NumBaseRegisters, "Number of virtual frame base registers allocated"); 43e580952dSDimitry Andric STATISTIC(NumReplacements, "Number of frame indices references replaced"); 44e580952dSDimitry Andric 45e580952dSDimitry Andric namespace { 46e580952dSDimitry Andric class FrameRef { 47e580952dSDimitry Andric MachineBasicBlock::iterator MI; // Instr referencing the frame 48e580952dSDimitry Andric int64_t LocalOffset; // Local offset of the frame idx referenced 49e580952dSDimitry Andric public: 50e580952dSDimitry Andric FrameRef(MachineBasicBlock::iterator I, int64_t Offset) : 51e580952dSDimitry Andric MI(I), LocalOffset(Offset) {} 52e580952dSDimitry Andric bool operator<(const FrameRef &RHS) const { 53e580952dSDimitry Andric return LocalOffset < RHS.LocalOffset; 54e580952dSDimitry Andric } 55e580952dSDimitry Andric MachineBasicBlock::iterator getMachineInstr() { return MI; } 56e580952dSDimitry Andric }; 57e580952dSDimitry Andric 58e580952dSDimitry Andric class LocalStackSlotPass: public MachineFunctionPass { 59e580952dSDimitry Andric SmallVector<int64_t,16> LocalOffsets; 60e580952dSDimitry Andric 61e580952dSDimitry Andric void AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx, int64_t &Offset, 62e580952dSDimitry Andric bool StackGrowsDown, unsigned &MaxAlign); 63e580952dSDimitry Andric void calculateFrameObjectOffsets(MachineFunction &Fn); 64e580952dSDimitry Andric bool insertFrameReferenceRegisters(MachineFunction &Fn); 65e580952dSDimitry Andric public: 66e580952dSDimitry Andric static char ID; // Pass identification, replacement for typeid 67e580952dSDimitry Andric explicit LocalStackSlotPass() : MachineFunctionPass(ID) { } 68e580952dSDimitry Andric bool runOnMachineFunction(MachineFunction &MF); 69e580952dSDimitry Andric 70e580952dSDimitry Andric virtual void getAnalysisUsage(AnalysisUsage &AU) const { 71e580952dSDimitry Andric AU.setPreservesCFG(); 72e580952dSDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 73e580952dSDimitry Andric } 74e580952dSDimitry Andric 75e580952dSDimitry Andric private: 76e580952dSDimitry Andric }; 77e580952dSDimitry Andric } // end anonymous namespace 78e580952dSDimitry Andric 79e580952dSDimitry Andric char LocalStackSlotPass::ID = 0; 80dff0c46cSDimitry Andric char &llvm::LocalStackSlotAllocationID = LocalStackSlotPass::ID; 81dff0c46cSDimitry Andric INITIALIZE_PASS(LocalStackSlotPass, "localstackalloc", 82dff0c46cSDimitry Andric "Local Stack Slot Allocation", false, false) 83e580952dSDimitry Andric 84e580952dSDimitry Andric bool LocalStackSlotPass::runOnMachineFunction(MachineFunction &MF) { 85e580952dSDimitry Andric MachineFrameInfo *MFI = MF.getFrameInfo(); 86e580952dSDimitry Andric const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); 87e580952dSDimitry Andric unsigned LocalObjectCount = MFI->getObjectIndexEnd(); 88e580952dSDimitry Andric 89e580952dSDimitry Andric // If the target doesn't want/need this pass, or if there are no locals 90e580952dSDimitry Andric // to consider, early exit. 91e580952dSDimitry Andric if (!TRI->requiresVirtualBaseRegisters(MF) || LocalObjectCount == 0) 92e580952dSDimitry Andric return true; 93e580952dSDimitry Andric 94e580952dSDimitry Andric // Make sure we have enough space to store the local offsets. 95e580952dSDimitry Andric LocalOffsets.resize(MFI->getObjectIndexEnd()); 96e580952dSDimitry Andric 97e580952dSDimitry Andric // Lay out the local blob. 98e580952dSDimitry Andric calculateFrameObjectOffsets(MF); 99e580952dSDimitry Andric 100e580952dSDimitry Andric // Insert virtual base registers to resolve frame index references. 101e580952dSDimitry Andric bool UsedBaseRegs = insertFrameReferenceRegisters(MF); 102e580952dSDimitry Andric 103e580952dSDimitry Andric // Tell MFI whether any base registers were allocated. PEI will only 104e580952dSDimitry Andric // want to use the local block allocations from this pass if there were any. 105e580952dSDimitry Andric // Otherwise, PEI can do a bit better job of getting the alignment right 106e580952dSDimitry Andric // without a hole at the start since it knows the alignment of the stack 107e580952dSDimitry Andric // at the start of local allocation, and this pass doesn't. 108e580952dSDimitry Andric MFI->setUseLocalStackAllocationBlock(UsedBaseRegs); 109e580952dSDimitry Andric 110e580952dSDimitry Andric return true; 111e580952dSDimitry Andric } 112e580952dSDimitry Andric 113e580952dSDimitry Andric /// AdjustStackOffset - Helper function used to adjust the stack frame offset. 114e580952dSDimitry Andric void LocalStackSlotPass::AdjustStackOffset(MachineFrameInfo *MFI, 115e580952dSDimitry Andric int FrameIdx, int64_t &Offset, 116e580952dSDimitry Andric bool StackGrowsDown, 117e580952dSDimitry Andric unsigned &MaxAlign) { 118e580952dSDimitry Andric // If the stack grows down, add the object size to find the lowest address. 119e580952dSDimitry Andric if (StackGrowsDown) 120e580952dSDimitry Andric Offset += MFI->getObjectSize(FrameIdx); 121e580952dSDimitry Andric 122e580952dSDimitry Andric unsigned Align = MFI->getObjectAlignment(FrameIdx); 123e580952dSDimitry Andric 124e580952dSDimitry Andric // If the alignment of this object is greater than that of the stack, then 125e580952dSDimitry Andric // increase the stack alignment to match. 126e580952dSDimitry Andric MaxAlign = std::max(MaxAlign, Align); 127e580952dSDimitry Andric 128e580952dSDimitry Andric // Adjust to alignment boundary. 129e580952dSDimitry Andric Offset = (Offset + Align - 1) / Align * Align; 130e580952dSDimitry Andric 131e580952dSDimitry Andric int64_t LocalOffset = StackGrowsDown ? -Offset : Offset; 132e580952dSDimitry Andric DEBUG(dbgs() << "Allocate FI(" << FrameIdx << ") to local offset " 133e580952dSDimitry Andric << LocalOffset << "\n"); 134e580952dSDimitry Andric // Keep the offset available for base register allocation 135e580952dSDimitry Andric LocalOffsets[FrameIdx] = LocalOffset; 136e580952dSDimitry Andric // And tell MFI about it for PEI to use later 137e580952dSDimitry Andric MFI->mapLocalFrameObject(FrameIdx, LocalOffset); 138e580952dSDimitry Andric 139e580952dSDimitry Andric if (!StackGrowsDown) 140e580952dSDimitry Andric Offset += MFI->getObjectSize(FrameIdx); 141e580952dSDimitry Andric 142e580952dSDimitry Andric ++NumAllocations; 143e580952dSDimitry Andric } 144e580952dSDimitry Andric 145e580952dSDimitry Andric /// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the 146e580952dSDimitry Andric /// abstract stack objects. 147e580952dSDimitry Andric /// 148e580952dSDimitry Andric void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) { 149e580952dSDimitry Andric // Loop over all of the stack objects, assigning sequential addresses... 150e580952dSDimitry Andric MachineFrameInfo *MFI = Fn.getFrameInfo(); 1512754fe60SDimitry Andric const TargetFrameLowering &TFI = *Fn.getTarget().getFrameLowering(); 152e580952dSDimitry Andric bool StackGrowsDown = 1532754fe60SDimitry Andric TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; 154e580952dSDimitry Andric int64_t Offset = 0; 155e580952dSDimitry Andric unsigned MaxAlign = 0; 156e580952dSDimitry Andric 157e580952dSDimitry Andric // Make sure that the stack protector comes before the local variables on the 158e580952dSDimitry Andric // stack. 159e580952dSDimitry Andric SmallSet<int, 16> LargeStackObjs; 160e580952dSDimitry Andric if (MFI->getStackProtectorIndex() >= 0) { 161e580952dSDimitry Andric AdjustStackOffset(MFI, MFI->getStackProtectorIndex(), Offset, 162e580952dSDimitry Andric StackGrowsDown, MaxAlign); 163e580952dSDimitry Andric 164e580952dSDimitry Andric // Assign large stack objects first. 165e580952dSDimitry Andric for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { 166e580952dSDimitry Andric if (MFI->isDeadObjectIndex(i)) 167e580952dSDimitry Andric continue; 168e580952dSDimitry Andric if (MFI->getStackProtectorIndex() == (int)i) 169e580952dSDimitry Andric continue; 170e580952dSDimitry Andric if (!MFI->MayNeedStackProtector(i)) 171e580952dSDimitry Andric continue; 172e580952dSDimitry Andric 173e580952dSDimitry Andric AdjustStackOffset(MFI, i, Offset, StackGrowsDown, MaxAlign); 174e580952dSDimitry Andric LargeStackObjs.insert(i); 175e580952dSDimitry Andric } 176e580952dSDimitry Andric } 177e580952dSDimitry Andric 178e580952dSDimitry Andric // Then assign frame offsets to stack objects that are not used to spill 179e580952dSDimitry Andric // callee saved registers. 180e580952dSDimitry Andric for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { 181e580952dSDimitry Andric if (MFI->isDeadObjectIndex(i)) 182e580952dSDimitry Andric continue; 183e580952dSDimitry Andric if (MFI->getStackProtectorIndex() == (int)i) 184e580952dSDimitry Andric continue; 185e580952dSDimitry Andric if (LargeStackObjs.count(i)) 186e580952dSDimitry Andric continue; 187e580952dSDimitry Andric 188e580952dSDimitry Andric AdjustStackOffset(MFI, i, Offset, StackGrowsDown, MaxAlign); 189e580952dSDimitry Andric } 190e580952dSDimitry Andric 191e580952dSDimitry Andric // Remember how big this blob of stack space is 192e580952dSDimitry Andric MFI->setLocalFrameSize(Offset); 193e580952dSDimitry Andric MFI->setLocalFrameMaxAlign(MaxAlign); 194e580952dSDimitry Andric } 195e580952dSDimitry Andric 196e580952dSDimitry Andric static inline bool 197e580952dSDimitry Andric lookupCandidateBaseReg(const SmallVector<std::pair<unsigned, int64_t>, 8> &Regs, 198e580952dSDimitry Andric std::pair<unsigned, int64_t> &RegOffset, 199e580952dSDimitry Andric int64_t FrameSizeAdjust, 200e580952dSDimitry Andric int64_t LocalFrameOffset, 201e580952dSDimitry Andric const MachineInstr *MI, 202e580952dSDimitry Andric const TargetRegisterInfo *TRI) { 203e580952dSDimitry Andric unsigned e = Regs.size(); 204e580952dSDimitry Andric for (unsigned i = 0; i < e; ++i) { 205e580952dSDimitry Andric RegOffset = Regs[i]; 206e580952dSDimitry Andric // Check if the relative offset from the where the base register references 207e580952dSDimitry Andric // to the target address is in range for the instruction. 208e580952dSDimitry Andric int64_t Offset = FrameSizeAdjust + LocalFrameOffset - RegOffset.second; 209e580952dSDimitry Andric if (TRI->isFrameOffsetLegal(MI, Offset)) 210e580952dSDimitry Andric return true; 211e580952dSDimitry Andric } 212e580952dSDimitry Andric return false; 213e580952dSDimitry Andric } 214e580952dSDimitry Andric 215e580952dSDimitry Andric bool LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { 216e580952dSDimitry Andric // Scan the function's instructions looking for frame index references. 217e580952dSDimitry Andric // For each, ask the target if it wants a virtual base register for it 218e580952dSDimitry Andric // based on what we can tell it about where the local will end up in the 219e580952dSDimitry Andric // stack frame. If it wants one, re-use a suitable one we've previously 220e580952dSDimitry Andric // allocated, or if there isn't one that fits the bill, allocate a new one 221e580952dSDimitry Andric // and ask the target to create a defining instruction for it. 222e580952dSDimitry Andric bool UsedBaseReg = false; 223e580952dSDimitry Andric 224e580952dSDimitry Andric MachineFrameInfo *MFI = Fn.getFrameInfo(); 225e580952dSDimitry Andric const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo(); 2262754fe60SDimitry Andric const TargetFrameLowering &TFI = *Fn.getTarget().getFrameLowering(); 227e580952dSDimitry Andric bool StackGrowsDown = 2282754fe60SDimitry Andric TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; 229e580952dSDimitry Andric 230e580952dSDimitry Andric // Collect all of the instructions in the block that reference 231e580952dSDimitry Andric // a frame index. Also store the frame index referenced to ease later 232e580952dSDimitry Andric // lookup. (For any insn that has more than one FI reference, we arbitrarily 233e580952dSDimitry Andric // choose the first one). 234e580952dSDimitry Andric SmallVector<FrameRef, 64> FrameReferenceInsns; 2352754fe60SDimitry Andric 236e580952dSDimitry Andric // A base register definition is a register + offset pair. 237e580952dSDimitry Andric SmallVector<std::pair<unsigned, int64_t>, 8> BaseRegisters; 238e580952dSDimitry Andric 239e580952dSDimitry Andric for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { 240e580952dSDimitry Andric for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { 241e580952dSDimitry Andric MachineInstr *MI = I; 2422754fe60SDimitry Andric 243e580952dSDimitry Andric // Debug value instructions can't be out of range, so they don't need 244e580952dSDimitry Andric // any updates. 245e580952dSDimitry Andric if (MI->isDebugValue()) 246e580952dSDimitry Andric continue; 2472754fe60SDimitry Andric 248e580952dSDimitry Andric // For now, allocate the base register(s) within the basic block 249e580952dSDimitry Andric // where they're used, and don't try to keep them around outside 250e580952dSDimitry Andric // of that. It may be beneficial to try sharing them more broadly 251e580952dSDimitry Andric // than that, but the increased register pressure makes that a 252e580952dSDimitry Andric // tricky thing to balance. Investigate if re-materializing these 253e580952dSDimitry Andric // becomes an issue. 254e580952dSDimitry Andric for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 255e580952dSDimitry Andric // Consider replacing all frame index operands that reference 256e580952dSDimitry Andric // an object allocated in the local block. 257e580952dSDimitry Andric if (MI->getOperand(i).isFI()) { 258e580952dSDimitry Andric // Don't try this with values not in the local block. 259e580952dSDimitry Andric if (!MFI->isObjectPreAllocated(MI->getOperand(i).getIndex())) 260e580952dSDimitry Andric break; 261e580952dSDimitry Andric FrameReferenceInsns. 262e580952dSDimitry Andric push_back(FrameRef(MI, LocalOffsets[MI->getOperand(i).getIndex()])); 263e580952dSDimitry Andric break; 264e580952dSDimitry Andric } 265e580952dSDimitry Andric } 266e580952dSDimitry Andric } 267e580952dSDimitry Andric } 2682754fe60SDimitry Andric 269e580952dSDimitry Andric // Sort the frame references by local offset 270e580952dSDimitry Andric array_pod_sort(FrameReferenceInsns.begin(), FrameReferenceInsns.end()); 271e580952dSDimitry Andric 2722754fe60SDimitry Andric MachineBasicBlock *Entry = Fn.begin(); 273e580952dSDimitry Andric 2742754fe60SDimitry Andric // Loop through the frame references and allocate for them as necessary. 275e580952dSDimitry Andric for (int ref = 0, e = FrameReferenceInsns.size(); ref < e ; ++ref) { 276e580952dSDimitry Andric MachineBasicBlock::iterator I = 277e580952dSDimitry Andric FrameReferenceInsns[ref].getMachineInstr(); 278e580952dSDimitry Andric MachineInstr *MI = I; 279e580952dSDimitry Andric for (unsigned idx = 0, e = MI->getNumOperands(); idx != e; ++idx) { 280e580952dSDimitry Andric // Consider replacing all frame index operands that reference 281e580952dSDimitry Andric // an object allocated in the local block. 282e580952dSDimitry Andric if (MI->getOperand(idx).isFI()) { 283e580952dSDimitry Andric int FrameIdx = MI->getOperand(idx).getIndex(); 284e580952dSDimitry Andric 285e580952dSDimitry Andric assert(MFI->isObjectPreAllocated(FrameIdx) && 286e580952dSDimitry Andric "Only pre-allocated locals expected!"); 287e580952dSDimitry Andric 288e580952dSDimitry Andric DEBUG(dbgs() << "Considering: " << *MI); 289e580952dSDimitry Andric if (TRI->needsFrameBaseReg(MI, LocalOffsets[FrameIdx])) { 290e580952dSDimitry Andric unsigned BaseReg = 0; 291e580952dSDimitry Andric int64_t Offset = 0; 292e580952dSDimitry Andric int64_t FrameSizeAdjust = 293e580952dSDimitry Andric StackGrowsDown ? MFI->getLocalFrameSize() : 0; 294e580952dSDimitry Andric 295e580952dSDimitry Andric DEBUG(dbgs() << " Replacing FI in: " << *MI); 296e580952dSDimitry Andric 297e580952dSDimitry Andric // If we have a suitable base register available, use it; otherwise 298e580952dSDimitry Andric // create a new one. Note that any offset encoded in the 299e580952dSDimitry Andric // instruction itself will be taken into account by the target, 300e580952dSDimitry Andric // so we don't have to adjust for it here when reusing a base 301e580952dSDimitry Andric // register. 302e580952dSDimitry Andric std::pair<unsigned, int64_t> RegOffset; 303e580952dSDimitry Andric if (lookupCandidateBaseReg(BaseRegisters, RegOffset, 304e580952dSDimitry Andric FrameSizeAdjust, 305e580952dSDimitry Andric LocalOffsets[FrameIdx], 306e580952dSDimitry Andric MI, TRI)) { 307e580952dSDimitry Andric DEBUG(dbgs() << " Reusing base register " << 308e580952dSDimitry Andric RegOffset.first << "\n"); 309e580952dSDimitry Andric // We found a register to reuse. 310e580952dSDimitry Andric BaseReg = RegOffset.first; 311e580952dSDimitry Andric Offset = FrameSizeAdjust + LocalOffsets[FrameIdx] - 312e580952dSDimitry Andric RegOffset.second; 313e580952dSDimitry Andric } else { 314e580952dSDimitry Andric // No previously defined register was in range, so create a 315e580952dSDimitry Andric // new one. 316e580952dSDimitry Andric int64_t InstrOffset = TRI->getFrameIndexInstrOffset(MI, idx); 317e580952dSDimitry Andric const TargetRegisterClass *RC = TRI->getPointerRegClass(); 318e580952dSDimitry Andric BaseReg = Fn.getRegInfo().createVirtualRegister(RC); 319e580952dSDimitry Andric 320e580952dSDimitry Andric DEBUG(dbgs() << " Materializing base register " << BaseReg << 321e580952dSDimitry Andric " at frame local offset " << 322e580952dSDimitry Andric LocalOffsets[FrameIdx] + InstrOffset << "\n"); 3232754fe60SDimitry Andric 324e580952dSDimitry Andric // Tell the target to insert the instruction to initialize 325e580952dSDimitry Andric // the base register. 3262754fe60SDimitry Andric // MachineBasicBlock::iterator InsertionPt = Entry->begin(); 3272754fe60SDimitry Andric TRI->materializeFrameBaseRegister(Entry, BaseReg, FrameIdx, 3282754fe60SDimitry Andric InstrOffset); 329e580952dSDimitry Andric 330e580952dSDimitry Andric // The base register already includes any offset specified 331e580952dSDimitry Andric // by the instruction, so account for that so it doesn't get 332e580952dSDimitry Andric // applied twice. 333e580952dSDimitry Andric Offset = -InstrOffset; 334e580952dSDimitry Andric 335e580952dSDimitry Andric int64_t BaseOffset = FrameSizeAdjust + LocalOffsets[FrameIdx] + 336e580952dSDimitry Andric InstrOffset; 337e580952dSDimitry Andric BaseRegisters.push_back( 338e580952dSDimitry Andric std::pair<unsigned, int64_t>(BaseReg, BaseOffset)); 339e580952dSDimitry Andric ++NumBaseRegisters; 340e580952dSDimitry Andric UsedBaseReg = true; 341e580952dSDimitry Andric } 342e580952dSDimitry Andric assert(BaseReg != 0 && "Unable to allocate virtual base register!"); 343e580952dSDimitry Andric 344e580952dSDimitry Andric // Modify the instruction to use the new base register rather 345e580952dSDimitry Andric // than the frame index operand. 346e580952dSDimitry Andric TRI->resolveFrameIndex(I, BaseReg, Offset); 347e580952dSDimitry Andric DEBUG(dbgs() << "Resolved: " << *MI); 348e580952dSDimitry Andric 349e580952dSDimitry Andric ++NumReplacements; 350e580952dSDimitry Andric } 351e580952dSDimitry Andric } 352e580952dSDimitry Andric } 353e580952dSDimitry Andric } 354e580952dSDimitry Andric return UsedBaseReg; 355e580952dSDimitry Andric } 356