1259698Sdim//===-- NVPTXPrologEpilogPass.cpp - NVPTX prolog/epilog inserter ----------===// 2259698Sdim// 3259698Sdim// The LLVM Compiler Infrastructure 4259698Sdim// 5259698Sdim// This file is distributed under the University of Illinois Open Source 6259698Sdim// License. See LICENSE.TXT for details. 7259698Sdim// 8259698Sdim//===----------------------------------------------------------------------===// 9259698Sdim// 10259698Sdim// This file is a copy of the generic LLVM PrologEpilogInserter pass, modified 11259698Sdim// to remove unneeded functionality and to handle virtual registers. Most code 12259698Sdim// here is a copy of PrologEpilogInserter.cpp. 13259698Sdim// 14259698Sdim//===----------------------------------------------------------------------===// 15259698Sdim 16259698Sdim#include "NVPTX.h" 17259698Sdim#include "llvm/Pass.h" 18259698Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 19259698Sdim#include "llvm/CodeGen/MachineFunction.h" 20259698Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 21259698Sdim#include "llvm/Target/TargetFrameLowering.h" 22259698Sdim#include "llvm/Target/TargetRegisterInfo.h" 23259698Sdim#include "llvm/Support/Debug.h" 24259698Sdim#include "llvm/Support/raw_ostream.h" 25259698Sdim 26259698Sdimusing namespace llvm; 27259698Sdim 28259698Sdimnamespace { 29259698Sdimclass NVPTXPrologEpilogPass : public MachineFunctionPass { 30259698Sdimpublic: 31259698Sdim static char ID; 32259698Sdim NVPTXPrologEpilogPass() : MachineFunctionPass(ID) {} 33259698Sdim 34259698Sdim virtual bool runOnMachineFunction(MachineFunction &MF); 35259698Sdim 36259698Sdimprivate: 37259698Sdim void calculateFrameObjectOffsets(MachineFunction &Fn); 38259698Sdim}; 39259698Sdim} 40259698Sdim 41259698SdimMachineFunctionPass *llvm::createNVPTXPrologEpilogPass() { 42259698Sdim return new NVPTXPrologEpilogPass(); 43259698Sdim} 44259698Sdim 45259698Sdimchar NVPTXPrologEpilogPass::ID = 0; 46259698Sdim 47259698Sdimbool NVPTXPrologEpilogPass::runOnMachineFunction(MachineFunction &MF) { 48259698Sdim const TargetMachine &TM = MF.getTarget(); 49259698Sdim const TargetFrameLowering &TFI = *TM.getFrameLowering(); 50259698Sdim const TargetRegisterInfo &TRI = *TM.getRegisterInfo(); 51259698Sdim bool Modified = false; 52259698Sdim 53259698Sdim calculateFrameObjectOffsets(MF); 54259698Sdim 55259698Sdim for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB) { 56259698Sdim for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { 57259698Sdim MachineInstr *MI = I; 58259698Sdim for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 59259698Sdim if (!MI->getOperand(i).isFI()) 60259698Sdim continue; 61259698Sdim TRI.eliminateFrameIndex(MI, 0, i, NULL); 62259698Sdim Modified = true; 63259698Sdim } 64259698Sdim } 65259698Sdim } 66259698Sdim 67259698Sdim // Add function prolog/epilog 68259698Sdim TFI.emitPrologue(MF); 69259698Sdim 70259698Sdim for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { 71259698Sdim // If last instruction is a return instruction, add an epilogue 72259698Sdim if (!I->empty() && I->back().isReturn()) 73259698Sdim TFI.emitEpilogue(MF, *I); 74259698Sdim } 75259698Sdim 76259698Sdim return Modified; 77259698Sdim} 78259698Sdim 79259698Sdim/// AdjustStackOffset - Helper function used to adjust the stack frame offset. 80259698Sdimstatic inline void 81259698SdimAdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx, 82259698Sdim bool StackGrowsDown, int64_t &Offset, 83259698Sdim unsigned &MaxAlign) { 84259698Sdim // If the stack grows down, add the object size to find the lowest address. 85259698Sdim if (StackGrowsDown) 86259698Sdim Offset += MFI->getObjectSize(FrameIdx); 87259698Sdim 88259698Sdim unsigned Align = MFI->getObjectAlignment(FrameIdx); 89259698Sdim 90259698Sdim // If the alignment of this object is greater than that of the stack, then 91259698Sdim // increase the stack alignment to match. 92259698Sdim MaxAlign = std::max(MaxAlign, Align); 93259698Sdim 94259698Sdim // Adjust to alignment boundary. 95259698Sdim Offset = (Offset + Align - 1) / Align * Align; 96259698Sdim 97259698Sdim if (StackGrowsDown) { 98259698Sdim DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset << "]\n"); 99259698Sdim MFI->setObjectOffset(FrameIdx, -Offset); // Set the computed offset 100259698Sdim } else { 101259698Sdim DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << Offset << "]\n"); 102259698Sdim MFI->setObjectOffset(FrameIdx, Offset); 103259698Sdim Offset += MFI->getObjectSize(FrameIdx); 104259698Sdim } 105259698Sdim} 106259698Sdim 107259698Sdimvoid 108259698SdimNVPTXPrologEpilogPass::calculateFrameObjectOffsets(MachineFunction &Fn) { 109259698Sdim const TargetFrameLowering &TFI = *Fn.getTarget().getFrameLowering(); 110259698Sdim const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo(); 111259698Sdim 112259698Sdim bool StackGrowsDown = 113259698Sdim TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; 114259698Sdim 115259698Sdim // Loop over all of the stack objects, assigning sequential addresses... 116259698Sdim MachineFrameInfo *MFI = Fn.getFrameInfo(); 117259698Sdim 118259698Sdim // Start at the beginning of the local area. 119259698Sdim // The Offset is the distance from the stack top in the direction 120259698Sdim // of stack growth -- so it's always nonnegative. 121259698Sdim int LocalAreaOffset = TFI.getOffsetOfLocalArea(); 122259698Sdim if (StackGrowsDown) 123259698Sdim LocalAreaOffset = -LocalAreaOffset; 124259698Sdim assert(LocalAreaOffset >= 0 125259698Sdim && "Local area offset should be in direction of stack growth"); 126259698Sdim int64_t Offset = LocalAreaOffset; 127259698Sdim 128259698Sdim // If there are fixed sized objects that are preallocated in the local area, 129259698Sdim // non-fixed objects can't be allocated right at the start of local area. 130259698Sdim // We currently don't support filling in holes in between fixed sized 131259698Sdim // objects, so we adjust 'Offset' to point to the end of last fixed sized 132259698Sdim // preallocated object. 133259698Sdim for (int i = MFI->getObjectIndexBegin(); i != 0; ++i) { 134259698Sdim int64_t FixedOff; 135259698Sdim if (StackGrowsDown) { 136259698Sdim // The maximum distance from the stack pointer is at lower address of 137259698Sdim // the object -- which is given by offset. For down growing stack 138259698Sdim // the offset is negative, so we negate the offset to get the distance. 139259698Sdim FixedOff = -MFI->getObjectOffset(i); 140259698Sdim } else { 141259698Sdim // The maximum distance from the start pointer is at the upper 142259698Sdim // address of the object. 143259698Sdim FixedOff = MFI->getObjectOffset(i) + MFI->getObjectSize(i); 144259698Sdim } 145259698Sdim if (FixedOff > Offset) Offset = FixedOff; 146259698Sdim } 147259698Sdim 148259698Sdim // NOTE: We do not have a call stack 149259698Sdim 150259698Sdim unsigned MaxAlign = MFI->getMaxAlignment(); 151259698Sdim 152259698Sdim // No scavenger 153259698Sdim 154259698Sdim // FIXME: Once this is working, then enable flag will change to a target 155259698Sdim // check for whether the frame is large enough to want to use virtual 156259698Sdim // frame index registers. Functions which don't want/need this optimization 157259698Sdim // will continue to use the existing code path. 158259698Sdim if (MFI->getUseLocalStackAllocationBlock()) { 159259698Sdim unsigned Align = MFI->getLocalFrameMaxAlign(); 160259698Sdim 161259698Sdim // Adjust to alignment boundary. 162259698Sdim Offset = (Offset + Align - 1) / Align * Align; 163259698Sdim 164259698Sdim DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n"); 165259698Sdim 166259698Sdim // Resolve offsets for objects in the local block. 167259698Sdim for (unsigned i = 0, e = MFI->getLocalFrameObjectCount(); i != e; ++i) { 168259698Sdim std::pair<int, int64_t> Entry = MFI->getLocalFrameObjectMap(i); 169259698Sdim int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second; 170259698Sdim DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" << 171259698Sdim FIOffset << "]\n"); 172259698Sdim MFI->setObjectOffset(Entry.first, FIOffset); 173259698Sdim } 174259698Sdim // Allocate the local block 175259698Sdim Offset += MFI->getLocalFrameSize(); 176259698Sdim 177259698Sdim MaxAlign = std::max(Align, MaxAlign); 178259698Sdim } 179259698Sdim 180259698Sdim // No stack protector 181259698Sdim 182259698Sdim // Then assign frame offsets to stack objects that are not used to spill 183259698Sdim // callee saved registers. 184259698Sdim for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { 185259698Sdim if (MFI->isObjectPreAllocated(i) && 186259698Sdim MFI->getUseLocalStackAllocationBlock()) 187259698Sdim continue; 188259698Sdim if (MFI->isDeadObjectIndex(i)) 189259698Sdim continue; 190259698Sdim 191259698Sdim AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign); 192259698Sdim } 193259698Sdim 194259698Sdim // No scavenger 195259698Sdim 196259698Sdim if (!TFI.targetHandlesStackFrameRounding()) { 197259698Sdim // If we have reserved argument space for call sites in the function 198259698Sdim // immediately on entry to the current function, count it as part of the 199259698Sdim // overall stack size. 200259698Sdim if (MFI->adjustsStack() && TFI.hasReservedCallFrame(Fn)) 201259698Sdim Offset += MFI->getMaxCallFrameSize(); 202259698Sdim 203259698Sdim // Round up the size to a multiple of the alignment. If the function has 204259698Sdim // any calls or alloca's, align to the target's StackAlignment value to 205259698Sdim // ensure that the callee's frame or the alloca data is suitably aligned; 206259698Sdim // otherwise, for leaf functions, align to the TransientStackAlignment 207259698Sdim // value. 208259698Sdim unsigned StackAlign; 209259698Sdim if (MFI->adjustsStack() || MFI->hasVarSizedObjects() || 210259698Sdim (RegInfo->needsStackRealignment(Fn) && MFI->getObjectIndexEnd() != 0)) 211259698Sdim StackAlign = TFI.getStackAlignment(); 212259698Sdim else 213259698Sdim StackAlign = TFI.getTransientStackAlignment(); 214259698Sdim 215259698Sdim // If the frame pointer is eliminated, all frame offsets will be relative to 216259698Sdim // SP not FP. Align to MaxAlign so this works. 217259698Sdim StackAlign = std::max(StackAlign, MaxAlign); 218259698Sdim unsigned AlignMask = StackAlign - 1; 219259698Sdim Offset = (Offset + AlignMask) & ~uint64_t(AlignMask); 220259698Sdim } 221259698Sdim 222259698Sdim // Update frame info to pretend that this is part of the stack... 223259698Sdim int64_t StackSize = Offset - LocalAreaOffset; 224259698Sdim MFI->setStackSize(StackSize); 225259698Sdim} 226