1259698Sdim//===-- NVPTXPrologEpilogPass.cpp - NVPTX prolog/epilog inserter ----------===// 2259698Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6259698Sdim// 7259698Sdim//===----------------------------------------------------------------------===// 8259698Sdim// 9259698Sdim// This file is a copy of the generic LLVM PrologEpilogInserter pass, modified 10259698Sdim// to remove unneeded functionality and to handle virtual registers. Most code 11259698Sdim// here is a copy of PrologEpilogInserter.cpp. 12259698Sdim// 13259698Sdim//===----------------------------------------------------------------------===// 14259698Sdim 15259698Sdim#include "NVPTX.h" 16259698Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 17259698Sdim#include "llvm/CodeGen/MachineFunction.h" 18259698Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 19327952Sdim#include "llvm/CodeGen/TargetFrameLowering.h" 20327952Sdim#include "llvm/CodeGen/TargetRegisterInfo.h" 21327952Sdim#include "llvm/CodeGen/TargetSubtargetInfo.h" 22344779Sdim#include "llvm/IR/DebugInfoMetadata.h" 23276479Sdim#include "llvm/Pass.h" 24276479Sdim#include "llvm/Support/Debug.h" 25276479Sdim#include "llvm/Support/raw_ostream.h" 26259698Sdim 27259698Sdimusing namespace llvm; 28259698Sdim 29276479Sdim#define DEBUG_TYPE "nvptx-prolog-epilog" 30276479Sdim 31259698Sdimnamespace { 32259698Sdimclass NVPTXPrologEpilogPass : public MachineFunctionPass { 33259698Sdimpublic: 34259698Sdim static char ID; 35259698Sdim NVPTXPrologEpilogPass() : MachineFunctionPass(ID) {} 36259698Sdim 37276479Sdim bool runOnMachineFunction(MachineFunction &MF) override; 38259698Sdim 39259698Sdimprivate: 40259698Sdim void calculateFrameObjectOffsets(MachineFunction &Fn); 41259698Sdim}; 42259698Sdim} 43259698Sdim 44259698SdimMachineFunctionPass *llvm::createNVPTXPrologEpilogPass() { 45259698Sdim return new NVPTXPrologEpilogPass(); 46259698Sdim} 47259698Sdim 48259698Sdimchar NVPTXPrologEpilogPass::ID = 0; 49259698Sdim 50259698Sdimbool NVPTXPrologEpilogPass::runOnMachineFunction(MachineFunction &MF) { 51288943Sdim const TargetSubtargetInfo &STI = MF.getSubtarget(); 52288943Sdim const TargetFrameLowering &TFI = *STI.getFrameLowering(); 53288943Sdim const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 54259698Sdim bool Modified = false; 55259698Sdim 56259698Sdim calculateFrameObjectOffsets(MF); 57259698Sdim 58309124Sdim for (MachineBasicBlock &MBB : MF) { 59309124Sdim for (MachineInstr &MI : MBB) { 60309124Sdim for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { 61309124Sdim if (!MI.getOperand(i).isFI()) 62259698Sdim continue; 63344779Sdim 64344779Sdim // Frame indices in debug values are encoded in a target independent 65344779Sdim // way with simply the frame index and offset rather than any 66344779Sdim // target-specific addressing mode. 67344779Sdim if (MI.isDebugValue()) { 68344779Sdim assert(i == 0 && "Frame indices can only appear as the first " 69344779Sdim "operand of a DBG_VALUE machine instruction"); 70344779Sdim unsigned Reg; 71344779Sdim int64_t Offset = 72344779Sdim TFI.getFrameIndexReference(MF, MI.getOperand(0).getIndex(), Reg); 73344779Sdim MI.getOperand(0).ChangeToRegister(Reg, /*isDef=*/false); 74344779Sdim MI.getOperand(0).setIsDebug(); 75353358Sdim auto *DIExpr = DIExpression::prepend( 76353358Sdim MI.getDebugExpression(), DIExpression::ApplyOffset, Offset); 77344779Sdim MI.getOperand(3).setMetadata(DIExpr); 78344779Sdim continue; 79344779Sdim } 80344779Sdim 81276479Sdim TRI.eliminateFrameIndex(MI, 0, i, nullptr); 82259698Sdim Modified = true; 83259698Sdim } 84259698Sdim } 85259698Sdim } 86259698Sdim 87259698Sdim // Add function prolog/epilog 88288943Sdim TFI.emitPrologue(MF, MF.front()); 89259698Sdim 90259698Sdim for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { 91259698Sdim // If last instruction is a return instruction, add an epilogue 92296417Sdim if (I->isReturnBlock()) 93259698Sdim TFI.emitEpilogue(MF, *I); 94259698Sdim } 95259698Sdim 96259698Sdim return Modified; 97259698Sdim} 98259698Sdim 99259698Sdim/// AdjustStackOffset - Helper function used to adjust the stack frame offset. 100259698Sdimstatic inline void 101314564SdimAdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx, 102259698Sdim bool StackGrowsDown, int64_t &Offset, 103259698Sdim unsigned &MaxAlign) { 104259698Sdim // If the stack grows down, add the object size to find the lowest address. 105259698Sdim if (StackGrowsDown) 106314564Sdim Offset += MFI.getObjectSize(FrameIdx); 107259698Sdim 108314564Sdim unsigned Align = MFI.getObjectAlignment(FrameIdx); 109259698Sdim 110259698Sdim // If the alignment of this object is greater than that of the stack, then 111259698Sdim // increase the stack alignment to match. 112259698Sdim MaxAlign = std::max(MaxAlign, Align); 113259698Sdim 114259698Sdim // Adjust to alignment boundary. 115259698Sdim Offset = (Offset + Align - 1) / Align * Align; 116259698Sdim 117259698Sdim if (StackGrowsDown) { 118341825Sdim LLVM_DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset 119341825Sdim << "]\n"); 120314564Sdim MFI.setObjectOffset(FrameIdx, -Offset); // Set the computed offset 121259698Sdim } else { 122341825Sdim LLVM_DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << Offset 123341825Sdim << "]\n"); 124314564Sdim MFI.setObjectOffset(FrameIdx, Offset); 125314564Sdim Offset += MFI.getObjectSize(FrameIdx); 126259698Sdim } 127259698Sdim} 128259698Sdim 129259698Sdimvoid 130259698SdimNVPTXPrologEpilogPass::calculateFrameObjectOffsets(MachineFunction &Fn) { 131280031Sdim const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering(); 132280031Sdim const TargetRegisterInfo *RegInfo = Fn.getSubtarget().getRegisterInfo(); 133259698Sdim 134259698Sdim bool StackGrowsDown = 135259698Sdim TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; 136259698Sdim 137259698Sdim // Loop over all of the stack objects, assigning sequential addresses... 138314564Sdim MachineFrameInfo &MFI = Fn.getFrameInfo(); 139259698Sdim 140259698Sdim // Start at the beginning of the local area. 141259698Sdim // The Offset is the distance from the stack top in the direction 142259698Sdim // of stack growth -- so it's always nonnegative. 143259698Sdim int LocalAreaOffset = TFI.getOffsetOfLocalArea(); 144259698Sdim if (StackGrowsDown) 145259698Sdim LocalAreaOffset = -LocalAreaOffset; 146259698Sdim assert(LocalAreaOffset >= 0 147259698Sdim && "Local area offset should be in direction of stack growth"); 148259698Sdim int64_t Offset = LocalAreaOffset; 149259698Sdim 150259698Sdim // If there are fixed sized objects that are preallocated in the local area, 151259698Sdim // non-fixed objects can't be allocated right at the start of local area. 152259698Sdim // We currently don't support filling in holes in between fixed sized 153259698Sdim // objects, so we adjust 'Offset' to point to the end of last fixed sized 154259698Sdim // preallocated object. 155314564Sdim for (int i = MFI.getObjectIndexBegin(); i != 0; ++i) { 156259698Sdim int64_t FixedOff; 157259698Sdim if (StackGrowsDown) { 158259698Sdim // The maximum distance from the stack pointer is at lower address of 159259698Sdim // the object -- which is given by offset. For down growing stack 160259698Sdim // the offset is negative, so we negate the offset to get the distance. 161314564Sdim FixedOff = -MFI.getObjectOffset(i); 162259698Sdim } else { 163259698Sdim // The maximum distance from the start pointer is at the upper 164259698Sdim // address of the object. 165314564Sdim FixedOff = MFI.getObjectOffset(i) + MFI.getObjectSize(i); 166259698Sdim } 167259698Sdim if (FixedOff > Offset) Offset = FixedOff; 168259698Sdim } 169259698Sdim 170259698Sdim // NOTE: We do not have a call stack 171259698Sdim 172314564Sdim unsigned MaxAlign = MFI.getMaxAlignment(); 173259698Sdim 174259698Sdim // No scavenger 175259698Sdim 176259698Sdim // FIXME: Once this is working, then enable flag will change to a target 177259698Sdim // check for whether the frame is large enough to want to use virtual 178259698Sdim // frame index registers. Functions which don't want/need this optimization 179259698Sdim // will continue to use the existing code path. 180314564Sdim if (MFI.getUseLocalStackAllocationBlock()) { 181360784Sdim unsigned Align = MFI.getLocalFrameMaxAlign().value(); 182259698Sdim 183259698Sdim // Adjust to alignment boundary. 184259698Sdim Offset = (Offset + Align - 1) / Align * Align; 185259698Sdim 186341825Sdim LLVM_DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n"); 187259698Sdim 188259698Sdim // Resolve offsets for objects in the local block. 189314564Sdim for (unsigned i = 0, e = MFI.getLocalFrameObjectCount(); i != e; ++i) { 190314564Sdim std::pair<int, int64_t> Entry = MFI.getLocalFrameObjectMap(i); 191259698Sdim int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second; 192341825Sdim LLVM_DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" << FIOffset 193341825Sdim << "]\n"); 194314564Sdim MFI.setObjectOffset(Entry.first, FIOffset); 195259698Sdim } 196259698Sdim // Allocate the local block 197314564Sdim Offset += MFI.getLocalFrameSize(); 198259698Sdim 199259698Sdim MaxAlign = std::max(Align, MaxAlign); 200259698Sdim } 201259698Sdim 202259698Sdim // No stack protector 203259698Sdim 204259698Sdim // Then assign frame offsets to stack objects that are not used to spill 205259698Sdim // callee saved registers. 206314564Sdim for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) { 207314564Sdim if (MFI.isObjectPreAllocated(i) && 208314564Sdim MFI.getUseLocalStackAllocationBlock()) 209259698Sdim continue; 210314564Sdim if (MFI.isDeadObjectIndex(i)) 211259698Sdim continue; 212259698Sdim 213259698Sdim AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign); 214259698Sdim } 215259698Sdim 216259698Sdim // No scavenger 217259698Sdim 218259698Sdim if (!TFI.targetHandlesStackFrameRounding()) { 219259698Sdim // If we have reserved argument space for call sites in the function 220259698Sdim // immediately on entry to the current function, count it as part of the 221259698Sdim // overall stack size. 222314564Sdim if (MFI.adjustsStack() && TFI.hasReservedCallFrame(Fn)) 223314564Sdim Offset += MFI.getMaxCallFrameSize(); 224259698Sdim 225259698Sdim // Round up the size to a multiple of the alignment. If the function has 226259698Sdim // any calls or alloca's, align to the target's StackAlignment value to 227259698Sdim // ensure that the callee's frame or the alloca data is suitably aligned; 228259698Sdim // otherwise, for leaf functions, align to the TransientStackAlignment 229259698Sdim // value. 230259698Sdim unsigned StackAlign; 231314564Sdim if (MFI.adjustsStack() || MFI.hasVarSizedObjects() || 232314564Sdim (RegInfo->needsStackRealignment(Fn) && MFI.getObjectIndexEnd() != 0)) 233259698Sdim StackAlign = TFI.getStackAlignment(); 234259698Sdim else 235259698Sdim StackAlign = TFI.getTransientStackAlignment(); 236259698Sdim 237259698Sdim // If the frame pointer is eliminated, all frame offsets will be relative to 238259698Sdim // SP not FP. Align to MaxAlign so this works. 239259698Sdim StackAlign = std::max(StackAlign, MaxAlign); 240259698Sdim unsigned AlignMask = StackAlign - 1; 241259698Sdim Offset = (Offset + AlignMask) & ~uint64_t(AlignMask); 242259698Sdim } 243259698Sdim 244259698Sdim // Update frame info to pretend that this is part of the stack... 245259698Sdim int64_t StackSize = Offset - LocalAreaOffset; 246314564Sdim MFI.setStackSize(StackSize); 247259698Sdim} 248