1*0b57cec5SDimitry Andric //===- LocalStackSlotAllocation.cpp - Pre-allocate locals to stack slots --===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This pass assigns local frame indices to stack slots relative to one another 10*0b57cec5SDimitry Andric // and allocates additional base registers to access them when the target 11*0b57cec5SDimitry Andric // estimates they are likely to be out of range of stack pointer and frame 12*0b57cec5SDimitry Andric // pointer relative addressing. 13*0b57cec5SDimitry Andric // 14*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h" 17*0b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h" 18*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 19*0b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 22*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 23*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 24*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 25*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 26*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 27*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h" 28*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h" 29*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 30*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 31480093f4SDimitry Andric #include "llvm/InitializePasses.h" 32*0b57cec5SDimitry Andric #include "llvm/Pass.h" 33*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 34*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 35*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 36*0b57cec5SDimitry Andric #include <algorithm> 37*0b57cec5SDimitry Andric #include <cassert> 38*0b57cec5SDimitry Andric #include <cstdint> 39*0b57cec5SDimitry Andric #include <tuple> 40*0b57cec5SDimitry Andric 41*0b57cec5SDimitry Andric using namespace llvm; 42*0b57cec5SDimitry Andric 43*0b57cec5SDimitry Andric #define DEBUG_TYPE "localstackalloc" 44*0b57cec5SDimitry Andric 45*0b57cec5SDimitry Andric STATISTIC(NumAllocations, "Number of frame indices allocated into local block"); 46*0b57cec5SDimitry Andric STATISTIC(NumBaseRegisters, "Number of virtual frame base registers allocated"); 47*0b57cec5SDimitry Andric STATISTIC(NumReplacements, "Number of frame indices references replaced"); 48*0b57cec5SDimitry Andric 49*0b57cec5SDimitry Andric namespace { 50*0b57cec5SDimitry Andric 51*0b57cec5SDimitry Andric class FrameRef { 52*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI; // Instr referencing the frame 53*0b57cec5SDimitry Andric int64_t LocalOffset; // Local offset of the frame idx referenced 54*0b57cec5SDimitry Andric int FrameIdx; // The frame index 55*0b57cec5SDimitry Andric 56*0b57cec5SDimitry Andric // Order reference instruction appears in program. Used to ensure 57*0b57cec5SDimitry Andric // deterministic order when multiple instructions may reference the same 58*0b57cec5SDimitry Andric // location. 59*0b57cec5SDimitry Andric unsigned Order; 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric public: 62*0b57cec5SDimitry Andric FrameRef(MachineInstr *I, int64_t Offset, int Idx, unsigned Ord) : 63*0b57cec5SDimitry Andric MI(I), LocalOffset(Offset), FrameIdx(Idx), Order(Ord) {} 64*0b57cec5SDimitry Andric 65*0b57cec5SDimitry Andric bool operator<(const FrameRef &RHS) const { 66*0b57cec5SDimitry Andric return std::tie(LocalOffset, FrameIdx, Order) < 67*0b57cec5SDimitry Andric std::tie(RHS.LocalOffset, RHS.FrameIdx, RHS.Order); 68*0b57cec5SDimitry Andric } 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric MachineBasicBlock::iterator getMachineInstr() const { return MI; } 71*0b57cec5SDimitry Andric int64_t getLocalOffset() const { return LocalOffset; } 72*0b57cec5SDimitry Andric int getFrameIndex() const { return FrameIdx; } 73*0b57cec5SDimitry Andric }; 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric class LocalStackSlotPass: public MachineFunctionPass { 76*0b57cec5SDimitry Andric SmallVector<int64_t, 16> LocalOffsets; 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric /// StackObjSet - A set of stack object indexes 79*0b57cec5SDimitry Andric using StackObjSet = SmallSetVector<int, 8>; 80*0b57cec5SDimitry Andric 81*0b57cec5SDimitry Andric void AdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx, int64_t &Offset, 825ffd83dbSDimitry Andric bool StackGrowsDown, Align &MaxAlign); 83*0b57cec5SDimitry Andric void AssignProtectedObjSet(const StackObjSet &UnassignedObjs, 84*0b57cec5SDimitry Andric SmallSet<int, 16> &ProtectedObjs, 85*0b57cec5SDimitry Andric MachineFrameInfo &MFI, bool StackGrowsDown, 865ffd83dbSDimitry Andric int64_t &Offset, Align &MaxAlign); 87*0b57cec5SDimitry Andric void calculateFrameObjectOffsets(MachineFunction &Fn); 88*0b57cec5SDimitry Andric bool insertFrameReferenceRegisters(MachineFunction &Fn); 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric public: 91*0b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric explicit LocalStackSlotPass() : MachineFunctionPass(ID) { 94*0b57cec5SDimitry Andric initializeLocalStackSlotPassPass(*PassRegistry::getPassRegistry()); 95*0b57cec5SDimitry Andric } 96*0b57cec5SDimitry Andric 97*0b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 100*0b57cec5SDimitry Andric AU.setPreservesCFG(); 101*0b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 102*0b57cec5SDimitry Andric } 103*0b57cec5SDimitry Andric }; 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric } // end anonymous namespace 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric char LocalStackSlotPass::ID = 0; 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric char &llvm::LocalStackSlotAllocationID = LocalStackSlotPass::ID; 110*0b57cec5SDimitry Andric INITIALIZE_PASS(LocalStackSlotPass, DEBUG_TYPE, 111*0b57cec5SDimitry Andric "Local Stack Slot Allocation", false, false) 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric bool LocalStackSlotPass::runOnMachineFunction(MachineFunction &MF) { 114*0b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 115*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 116*0b57cec5SDimitry Andric unsigned LocalObjectCount = MFI.getObjectIndexEnd(); 117*0b57cec5SDimitry Andric 118*0b57cec5SDimitry Andric // If the target doesn't want/need this pass, or if there are no locals 119*0b57cec5SDimitry Andric // to consider, early exit. 120*0b57cec5SDimitry Andric if (!TRI->requiresVirtualBaseRegisters(MF) || LocalObjectCount == 0) 121*0b57cec5SDimitry Andric return true; 122*0b57cec5SDimitry Andric 123*0b57cec5SDimitry Andric // Make sure we have enough space to store the local offsets. 124*0b57cec5SDimitry Andric LocalOffsets.resize(MFI.getObjectIndexEnd()); 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric // Lay out the local blob. 127*0b57cec5SDimitry Andric calculateFrameObjectOffsets(MF); 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric // Insert virtual base registers to resolve frame index references. 130*0b57cec5SDimitry Andric bool UsedBaseRegs = insertFrameReferenceRegisters(MF); 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric // Tell MFI whether any base registers were allocated. PEI will only 133*0b57cec5SDimitry Andric // want to use the local block allocations from this pass if there were any. 134*0b57cec5SDimitry Andric // Otherwise, PEI can do a bit better job of getting the alignment right 135*0b57cec5SDimitry Andric // without a hole at the start since it knows the alignment of the stack 136*0b57cec5SDimitry Andric // at the start of local allocation, and this pass doesn't. 137*0b57cec5SDimitry Andric MFI.setUseLocalStackAllocationBlock(UsedBaseRegs); 138*0b57cec5SDimitry Andric 139*0b57cec5SDimitry Andric return true; 140*0b57cec5SDimitry Andric } 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric /// AdjustStackOffset - Helper function used to adjust the stack frame offset. 1435ffd83dbSDimitry Andric void LocalStackSlotPass::AdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx, 1445ffd83dbSDimitry Andric int64_t &Offset, bool StackGrowsDown, 1455ffd83dbSDimitry Andric Align &MaxAlign) { 146*0b57cec5SDimitry Andric // If the stack grows down, add the object size to find the lowest address. 147*0b57cec5SDimitry Andric if (StackGrowsDown) 148*0b57cec5SDimitry Andric Offset += MFI.getObjectSize(FrameIdx); 149*0b57cec5SDimitry Andric 1505ffd83dbSDimitry Andric Align Alignment = MFI.getObjectAlign(FrameIdx); 151*0b57cec5SDimitry Andric 152*0b57cec5SDimitry Andric // If the alignment of this object is greater than that of the stack, then 153*0b57cec5SDimitry Andric // increase the stack alignment to match. 1545ffd83dbSDimitry Andric MaxAlign = std::max(MaxAlign, Alignment); 155*0b57cec5SDimitry Andric 156*0b57cec5SDimitry Andric // Adjust to alignment boundary. 1575ffd83dbSDimitry Andric Offset = alignTo(Offset, Alignment); 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric int64_t LocalOffset = StackGrowsDown ? -Offset : Offset; 160*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Allocate FI(" << FrameIdx << ") to local offset " 161*0b57cec5SDimitry Andric << LocalOffset << "\n"); 162*0b57cec5SDimitry Andric // Keep the offset available for base register allocation 163*0b57cec5SDimitry Andric LocalOffsets[FrameIdx] = LocalOffset; 164*0b57cec5SDimitry Andric // And tell MFI about it for PEI to use later 165*0b57cec5SDimitry Andric MFI.mapLocalFrameObject(FrameIdx, LocalOffset); 166*0b57cec5SDimitry Andric 167*0b57cec5SDimitry Andric if (!StackGrowsDown) 168*0b57cec5SDimitry Andric Offset += MFI.getObjectSize(FrameIdx); 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric ++NumAllocations; 171*0b57cec5SDimitry Andric } 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric /// AssignProtectedObjSet - Helper function to assign large stack objects (i.e., 174*0b57cec5SDimitry Andric /// those required to be close to the Stack Protector) to stack offsets. 1755ffd83dbSDimitry Andric void LocalStackSlotPass::AssignProtectedObjSet( 1765ffd83dbSDimitry Andric const StackObjSet &UnassignedObjs, SmallSet<int, 16> &ProtectedObjs, 1775ffd83dbSDimitry Andric MachineFrameInfo &MFI, bool StackGrowsDown, int64_t &Offset, 1785ffd83dbSDimitry Andric Align &MaxAlign) { 179*0b57cec5SDimitry Andric for (StackObjSet::const_iterator I = UnassignedObjs.begin(), 180*0b57cec5SDimitry Andric E = UnassignedObjs.end(); I != E; ++I) { 181*0b57cec5SDimitry Andric int i = *I; 182*0b57cec5SDimitry Andric AdjustStackOffset(MFI, i, Offset, StackGrowsDown, MaxAlign); 183*0b57cec5SDimitry Andric ProtectedObjs.insert(i); 184*0b57cec5SDimitry Andric } 185*0b57cec5SDimitry Andric } 186*0b57cec5SDimitry Andric 187*0b57cec5SDimitry Andric /// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the 188*0b57cec5SDimitry Andric /// abstract stack objects. 189*0b57cec5SDimitry Andric void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) { 190*0b57cec5SDimitry Andric // Loop over all of the stack objects, assigning sequential addresses... 191*0b57cec5SDimitry Andric MachineFrameInfo &MFI = Fn.getFrameInfo(); 192*0b57cec5SDimitry Andric const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering(); 193*0b57cec5SDimitry Andric bool StackGrowsDown = 194*0b57cec5SDimitry Andric TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; 195*0b57cec5SDimitry Andric int64_t Offset = 0; 1965ffd83dbSDimitry Andric Align MaxAlign; 197*0b57cec5SDimitry Andric 198*0b57cec5SDimitry Andric // Make sure that the stack protector comes before the local variables on the 199*0b57cec5SDimitry Andric // stack. 200*0b57cec5SDimitry Andric SmallSet<int, 16> ProtectedObjs; 201*0b57cec5SDimitry Andric if (MFI.hasStackProtectorIndex()) { 202*0b57cec5SDimitry Andric int StackProtectorFI = MFI.getStackProtectorIndex(); 203*0b57cec5SDimitry Andric 204*0b57cec5SDimitry Andric // We need to make sure we didn't pre-allocate the stack protector when 205*0b57cec5SDimitry Andric // doing this. 206*0b57cec5SDimitry Andric // If we already have a stack protector, this will re-assign it to a slot 207*0b57cec5SDimitry Andric // that is **not** covering the protected objects. 208*0b57cec5SDimitry Andric assert(!MFI.isObjectPreAllocated(StackProtectorFI) && 209*0b57cec5SDimitry Andric "Stack protector pre-allocated in LocalStackSlotAllocation"); 210*0b57cec5SDimitry Andric 211*0b57cec5SDimitry Andric StackObjSet LargeArrayObjs; 212*0b57cec5SDimitry Andric StackObjSet SmallArrayObjs; 213*0b57cec5SDimitry Andric StackObjSet AddrOfObjs; 214*0b57cec5SDimitry Andric 215*0b57cec5SDimitry Andric AdjustStackOffset(MFI, StackProtectorFI, Offset, StackGrowsDown, MaxAlign); 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric // Assign large stack objects first. 218*0b57cec5SDimitry Andric for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) { 219*0b57cec5SDimitry Andric if (MFI.isDeadObjectIndex(i)) 220*0b57cec5SDimitry Andric continue; 221*0b57cec5SDimitry Andric if (StackProtectorFI == (int)i) 222*0b57cec5SDimitry Andric continue; 223*0b57cec5SDimitry Andric 224*0b57cec5SDimitry Andric switch (MFI.getObjectSSPLayout(i)) { 225*0b57cec5SDimitry Andric case MachineFrameInfo::SSPLK_None: 226*0b57cec5SDimitry Andric continue; 227*0b57cec5SDimitry Andric case MachineFrameInfo::SSPLK_SmallArray: 228*0b57cec5SDimitry Andric SmallArrayObjs.insert(i); 229*0b57cec5SDimitry Andric continue; 230*0b57cec5SDimitry Andric case MachineFrameInfo::SSPLK_AddrOf: 231*0b57cec5SDimitry Andric AddrOfObjs.insert(i); 232*0b57cec5SDimitry Andric continue; 233*0b57cec5SDimitry Andric case MachineFrameInfo::SSPLK_LargeArray: 234*0b57cec5SDimitry Andric LargeArrayObjs.insert(i); 235*0b57cec5SDimitry Andric continue; 236*0b57cec5SDimitry Andric } 237*0b57cec5SDimitry Andric llvm_unreachable("Unexpected SSPLayoutKind."); 238*0b57cec5SDimitry Andric } 239*0b57cec5SDimitry Andric 240*0b57cec5SDimitry Andric AssignProtectedObjSet(LargeArrayObjs, ProtectedObjs, MFI, StackGrowsDown, 241*0b57cec5SDimitry Andric Offset, MaxAlign); 242*0b57cec5SDimitry Andric AssignProtectedObjSet(SmallArrayObjs, ProtectedObjs, MFI, StackGrowsDown, 243*0b57cec5SDimitry Andric Offset, MaxAlign); 244*0b57cec5SDimitry Andric AssignProtectedObjSet(AddrOfObjs, ProtectedObjs, MFI, StackGrowsDown, 245*0b57cec5SDimitry Andric Offset, MaxAlign); 246*0b57cec5SDimitry Andric } 247*0b57cec5SDimitry Andric 248*0b57cec5SDimitry Andric // Then assign frame offsets to stack objects that are not used to spill 249*0b57cec5SDimitry Andric // callee saved registers. 250*0b57cec5SDimitry Andric for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) { 251*0b57cec5SDimitry Andric if (MFI.isDeadObjectIndex(i)) 252*0b57cec5SDimitry Andric continue; 253*0b57cec5SDimitry Andric if (MFI.getStackProtectorIndex() == (int)i) 254*0b57cec5SDimitry Andric continue; 255*0b57cec5SDimitry Andric if (ProtectedObjs.count(i)) 256*0b57cec5SDimitry Andric continue; 257*0b57cec5SDimitry Andric 258*0b57cec5SDimitry Andric AdjustStackOffset(MFI, i, Offset, StackGrowsDown, MaxAlign); 259*0b57cec5SDimitry Andric } 260*0b57cec5SDimitry Andric 261*0b57cec5SDimitry Andric // Remember how big this blob of stack space is 262*0b57cec5SDimitry Andric MFI.setLocalFrameSize(Offset); 2635ffd83dbSDimitry Andric MFI.setLocalFrameMaxAlign(MaxAlign); 264*0b57cec5SDimitry Andric } 265*0b57cec5SDimitry Andric 266*0b57cec5SDimitry Andric static inline bool 267*0b57cec5SDimitry Andric lookupCandidateBaseReg(unsigned BaseReg, 268*0b57cec5SDimitry Andric int64_t BaseOffset, 269*0b57cec5SDimitry Andric int64_t FrameSizeAdjust, 270*0b57cec5SDimitry Andric int64_t LocalFrameOffset, 271*0b57cec5SDimitry Andric const MachineInstr &MI, 272*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 273*0b57cec5SDimitry Andric // Check if the relative offset from the where the base register references 274*0b57cec5SDimitry Andric // to the target address is in range for the instruction. 275*0b57cec5SDimitry Andric int64_t Offset = FrameSizeAdjust + LocalFrameOffset - BaseOffset; 276*0b57cec5SDimitry Andric return TRI->isFrameOffsetLegal(&MI, BaseReg, Offset); 277*0b57cec5SDimitry Andric } 278*0b57cec5SDimitry Andric 279*0b57cec5SDimitry Andric bool LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { 280*0b57cec5SDimitry Andric // Scan the function's instructions looking for frame index references. 281*0b57cec5SDimitry Andric // For each, ask the target if it wants a virtual base register for it 282*0b57cec5SDimitry Andric // based on what we can tell it about where the local will end up in the 283*0b57cec5SDimitry Andric // stack frame. If it wants one, re-use a suitable one we've previously 284*0b57cec5SDimitry Andric // allocated, or if there isn't one that fits the bill, allocate a new one 285*0b57cec5SDimitry Andric // and ask the target to create a defining instruction for it. 286*0b57cec5SDimitry Andric bool UsedBaseReg = false; 287*0b57cec5SDimitry Andric 288*0b57cec5SDimitry Andric MachineFrameInfo &MFI = Fn.getFrameInfo(); 289*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo(); 290*0b57cec5SDimitry Andric const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering(); 291*0b57cec5SDimitry Andric bool StackGrowsDown = 292*0b57cec5SDimitry Andric TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; 293*0b57cec5SDimitry Andric 294*0b57cec5SDimitry Andric // Collect all of the instructions in the block that reference 295*0b57cec5SDimitry Andric // a frame index. Also store the frame index referenced to ease later 296*0b57cec5SDimitry Andric // lookup. (For any insn that has more than one FI reference, we arbitrarily 297*0b57cec5SDimitry Andric // choose the first one). 298*0b57cec5SDimitry Andric SmallVector<FrameRef, 64> FrameReferenceInsns; 299*0b57cec5SDimitry Andric 300*0b57cec5SDimitry Andric unsigned Order = 0; 301*0b57cec5SDimitry Andric 302*0b57cec5SDimitry Andric for (MachineBasicBlock &BB : Fn) { 303*0b57cec5SDimitry Andric for (MachineInstr &MI : BB) { 304*0b57cec5SDimitry Andric // Debug value, stackmap and patchpoint instructions can't be out of 305*0b57cec5SDimitry Andric // range, so they don't need any updates. 306*0b57cec5SDimitry Andric if (MI.isDebugInstr() || MI.getOpcode() == TargetOpcode::STATEPOINT || 307*0b57cec5SDimitry Andric MI.getOpcode() == TargetOpcode::STACKMAP || 308*0b57cec5SDimitry Andric MI.getOpcode() == TargetOpcode::PATCHPOINT) 309*0b57cec5SDimitry Andric continue; 310*0b57cec5SDimitry Andric 311*0b57cec5SDimitry Andric // For now, allocate the base register(s) within the basic block 312*0b57cec5SDimitry Andric // where they're used, and don't try to keep them around outside 313*0b57cec5SDimitry Andric // of that. It may be beneficial to try sharing them more broadly 314*0b57cec5SDimitry Andric // than that, but the increased register pressure makes that a 315*0b57cec5SDimitry Andric // tricky thing to balance. Investigate if re-materializing these 316*0b57cec5SDimitry Andric // becomes an issue. 317*0b57cec5SDimitry Andric for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { 318*0b57cec5SDimitry Andric // Consider replacing all frame index operands that reference 319*0b57cec5SDimitry Andric // an object allocated in the local block. 320*0b57cec5SDimitry Andric if (MI.getOperand(i).isFI()) { 321*0b57cec5SDimitry Andric // Don't try this with values not in the local block. 322*0b57cec5SDimitry Andric if (!MFI.isObjectPreAllocated(MI.getOperand(i).getIndex())) 323*0b57cec5SDimitry Andric break; 324*0b57cec5SDimitry Andric int Idx = MI.getOperand(i).getIndex(); 325*0b57cec5SDimitry Andric int64_t LocalOffset = LocalOffsets[Idx]; 326*0b57cec5SDimitry Andric if (!TRI->needsFrameBaseReg(&MI, LocalOffset)) 327*0b57cec5SDimitry Andric break; 328*0b57cec5SDimitry Andric FrameReferenceInsns.push_back(FrameRef(&MI, LocalOffset, Idx, Order++)); 329*0b57cec5SDimitry Andric break; 330*0b57cec5SDimitry Andric } 331*0b57cec5SDimitry Andric } 332*0b57cec5SDimitry Andric } 333*0b57cec5SDimitry Andric } 334*0b57cec5SDimitry Andric 335*0b57cec5SDimitry Andric // Sort the frame references by local offset. 336*0b57cec5SDimitry Andric // Use frame index as a tie-breaker in case MI's have the same offset. 337*0b57cec5SDimitry Andric llvm::sort(FrameReferenceInsns); 338*0b57cec5SDimitry Andric 339*0b57cec5SDimitry Andric MachineBasicBlock *Entry = &Fn.front(); 340*0b57cec5SDimitry Andric 341*0b57cec5SDimitry Andric unsigned BaseReg = 0; 342*0b57cec5SDimitry Andric int64_t BaseOffset = 0; 343*0b57cec5SDimitry Andric 344*0b57cec5SDimitry Andric // Loop through the frame references and allocate for them as necessary. 345*0b57cec5SDimitry Andric for (int ref = 0, e = FrameReferenceInsns.size(); ref < e ; ++ref) { 346*0b57cec5SDimitry Andric FrameRef &FR = FrameReferenceInsns[ref]; 347*0b57cec5SDimitry Andric MachineInstr &MI = *FR.getMachineInstr(); 348*0b57cec5SDimitry Andric int64_t LocalOffset = FR.getLocalOffset(); 349*0b57cec5SDimitry Andric int FrameIdx = FR.getFrameIndex(); 350*0b57cec5SDimitry Andric assert(MFI.isObjectPreAllocated(FrameIdx) && 351*0b57cec5SDimitry Andric "Only pre-allocated locals expected!"); 352*0b57cec5SDimitry Andric 353*0b57cec5SDimitry Andric // We need to keep the references to the stack protector slot through frame 354*0b57cec5SDimitry Andric // index operands so that it gets resolved by PEI rather than this pass. 355*0b57cec5SDimitry Andric // This avoids accesses to the stack protector though virtual base 356*0b57cec5SDimitry Andric // registers, and forces PEI to address it using fp/sp/bp. 357*0b57cec5SDimitry Andric if (MFI.hasStackProtectorIndex() && 358*0b57cec5SDimitry Andric FrameIdx == MFI.getStackProtectorIndex()) 359*0b57cec5SDimitry Andric continue; 360*0b57cec5SDimitry Andric 361*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Considering: " << MI); 362*0b57cec5SDimitry Andric 363*0b57cec5SDimitry Andric unsigned idx = 0; 364*0b57cec5SDimitry Andric for (unsigned f = MI.getNumOperands(); idx != f; ++idx) { 365*0b57cec5SDimitry Andric if (!MI.getOperand(idx).isFI()) 366*0b57cec5SDimitry Andric continue; 367*0b57cec5SDimitry Andric 368*0b57cec5SDimitry Andric if (FrameIdx == MI.getOperand(idx).getIndex()) 369*0b57cec5SDimitry Andric break; 370*0b57cec5SDimitry Andric } 371*0b57cec5SDimitry Andric 372*0b57cec5SDimitry Andric assert(idx < MI.getNumOperands() && "Cannot find FI operand"); 373*0b57cec5SDimitry Andric 374*0b57cec5SDimitry Andric int64_t Offset = 0; 375*0b57cec5SDimitry Andric int64_t FrameSizeAdjust = StackGrowsDown ? MFI.getLocalFrameSize() : 0; 376*0b57cec5SDimitry Andric 377*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Replacing FI in: " << MI); 378*0b57cec5SDimitry Andric 379*0b57cec5SDimitry Andric // If we have a suitable base register available, use it; otherwise 380*0b57cec5SDimitry Andric // create a new one. Note that any offset encoded in the 381*0b57cec5SDimitry Andric // instruction itself will be taken into account by the target, 382*0b57cec5SDimitry Andric // so we don't have to adjust for it here when reusing a base 383*0b57cec5SDimitry Andric // register. 384*0b57cec5SDimitry Andric if (UsedBaseReg && 385*0b57cec5SDimitry Andric lookupCandidateBaseReg(BaseReg, BaseOffset, FrameSizeAdjust, 386*0b57cec5SDimitry Andric LocalOffset, MI, TRI)) { 387*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Reusing base register " << BaseReg << "\n"); 388*0b57cec5SDimitry Andric // We found a register to reuse. 389*0b57cec5SDimitry Andric Offset = FrameSizeAdjust + LocalOffset - BaseOffset; 390*0b57cec5SDimitry Andric } else { 391*0b57cec5SDimitry Andric // No previously defined register was in range, so create a new one. 392*0b57cec5SDimitry Andric int64_t InstrOffset = TRI->getFrameIndexInstrOffset(&MI, idx); 393*0b57cec5SDimitry Andric 394*0b57cec5SDimitry Andric int64_t PrevBaseOffset = BaseOffset; 395*0b57cec5SDimitry Andric BaseOffset = FrameSizeAdjust + LocalOffset + InstrOffset; 396*0b57cec5SDimitry Andric 397*0b57cec5SDimitry Andric // We'd like to avoid creating single-use virtual base registers. 398*0b57cec5SDimitry Andric // Because the FrameRefs are in sorted order, and we've already 399*0b57cec5SDimitry Andric // processed all FrameRefs before this one, just check whether or not 400*0b57cec5SDimitry Andric // the next FrameRef will be able to reuse this new register. If not, 401*0b57cec5SDimitry Andric // then don't bother creating it. 402*0b57cec5SDimitry Andric if (ref + 1 >= e || 403*0b57cec5SDimitry Andric !lookupCandidateBaseReg( 404*0b57cec5SDimitry Andric BaseReg, BaseOffset, FrameSizeAdjust, 405*0b57cec5SDimitry Andric FrameReferenceInsns[ref + 1].getLocalOffset(), 406*0b57cec5SDimitry Andric *FrameReferenceInsns[ref + 1].getMachineInstr(), TRI)) { 407*0b57cec5SDimitry Andric BaseOffset = PrevBaseOffset; 408*0b57cec5SDimitry Andric continue; 409*0b57cec5SDimitry Andric } 410*0b57cec5SDimitry Andric 411*0b57cec5SDimitry Andric const MachineFunction *MF = MI.getMF(); 412*0b57cec5SDimitry Andric const TargetRegisterClass *RC = TRI->getPointerRegClass(*MF); 413*0b57cec5SDimitry Andric BaseReg = Fn.getRegInfo().createVirtualRegister(RC); 414*0b57cec5SDimitry Andric 415*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Materializing base register " << BaseReg 416*0b57cec5SDimitry Andric << " at frame local offset " 417*0b57cec5SDimitry Andric << LocalOffset + InstrOffset << "\n"); 418*0b57cec5SDimitry Andric 419*0b57cec5SDimitry Andric // Tell the target to insert the instruction to initialize 420*0b57cec5SDimitry Andric // the base register. 421*0b57cec5SDimitry Andric // MachineBasicBlock::iterator InsertionPt = Entry->begin(); 422*0b57cec5SDimitry Andric TRI->materializeFrameBaseRegister(Entry, BaseReg, FrameIdx, 423*0b57cec5SDimitry Andric InstrOffset); 424*0b57cec5SDimitry Andric 425*0b57cec5SDimitry Andric // The base register already includes any offset specified 426*0b57cec5SDimitry Andric // by the instruction, so account for that so it doesn't get 427*0b57cec5SDimitry Andric // applied twice. 428*0b57cec5SDimitry Andric Offset = -InstrOffset; 429*0b57cec5SDimitry Andric 430*0b57cec5SDimitry Andric ++NumBaseRegisters; 431*0b57cec5SDimitry Andric UsedBaseReg = true; 432*0b57cec5SDimitry Andric } 433*0b57cec5SDimitry Andric assert(BaseReg != 0 && "Unable to allocate virtual base register!"); 434*0b57cec5SDimitry Andric 435*0b57cec5SDimitry Andric // Modify the instruction to use the new base register rather 436*0b57cec5SDimitry Andric // than the frame index operand. 437*0b57cec5SDimitry Andric TRI->resolveFrameIndex(MI, BaseReg, Offset); 438*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Resolved: " << MI); 439*0b57cec5SDimitry Andric 440*0b57cec5SDimitry Andric ++NumReplacements; 441*0b57cec5SDimitry Andric } 442*0b57cec5SDimitry Andric 443*0b57cec5SDimitry Andric return UsedBaseReg; 444*0b57cec5SDimitry Andric } 445