Path: blob/main/contrib/llvm-project/llvm/lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp
35271 views
//===-- NVPTXPrologEpilogPass.cpp - NVPTX prolog/epilog inserter ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is a copy of the generic LLVM PrologEpilogInserter pass, modified9// to remove unneeded functionality and to handle virtual registers. Most code10// here is a copy of PrologEpilogInserter.cpp.11//12//===----------------------------------------------------------------------===//1314#include "NVPTX.h"15#include "llvm/CodeGen/MachineFrameInfo.h"16#include "llvm/CodeGen/MachineFunction.h"17#include "llvm/CodeGen/MachineFunctionPass.h"18#include "llvm/CodeGen/TargetFrameLowering.h"19#include "llvm/CodeGen/TargetRegisterInfo.h"20#include "llvm/CodeGen/TargetSubtargetInfo.h"21#include "llvm/IR/DebugInfoMetadata.h"22#include "llvm/Pass.h"23#include "llvm/Support/Debug.h"24#include "llvm/Support/raw_ostream.h"2526using namespace llvm;2728#define DEBUG_TYPE "nvptx-prolog-epilog"2930namespace {31class NVPTXPrologEpilogPass : public MachineFunctionPass {32public:33static char ID;34NVPTXPrologEpilogPass() : MachineFunctionPass(ID) {}3536bool runOnMachineFunction(MachineFunction &MF) override;3738StringRef getPassName() const override { return "NVPTX Prolog Epilog Pass"; }3940private:41void calculateFrameObjectOffsets(MachineFunction &Fn);42};43}4445MachineFunctionPass *llvm::createNVPTXPrologEpilogPass() {46return new NVPTXPrologEpilogPass();47}4849char NVPTXPrologEpilogPass::ID = 0;5051bool NVPTXPrologEpilogPass::runOnMachineFunction(MachineFunction &MF) {52const TargetSubtargetInfo &STI = MF.getSubtarget();53const TargetFrameLowering &TFI = *STI.getFrameLowering();54const TargetRegisterInfo &TRI = *STI.getRegisterInfo();55bool Modified = false;5657calculateFrameObjectOffsets(MF);5859for (MachineBasicBlock &MBB : MF) {60for (MachineInstr &MI : MBB) {61for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {62if (!MI.getOperand(i).isFI())63continue;6465// Frame indices in debug values are encoded in a target independent66// way with simply the frame index and offset rather than any67// target-specific addressing mode.68if (MI.isDebugValue()) {69MachineOperand &Op = MI.getOperand(i);70assert(71MI.isDebugOperand(&Op) &&72"Frame indices can only appear as a debug operand in a DBG_VALUE*"73" machine instruction");74Register Reg;75auto Offset =76TFI.getFrameIndexReference(MF, Op.getIndex(), Reg);77Op.ChangeToRegister(Reg, /*isDef=*/false);78const DIExpression *DIExpr = MI.getDebugExpression();79if (MI.isNonListDebugValue()) {80DIExpr = TRI.prependOffsetExpression(MI.getDebugExpression(), DIExpression::ApplyOffset, Offset);81} else {82SmallVector<uint64_t, 3> Ops;83TRI.getOffsetOpcodes(Offset, Ops);84unsigned OpIdx = MI.getDebugOperandIndex(&Op);85DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, OpIdx);86}87MI.getDebugExpressionOp().setMetadata(DIExpr);88continue;89}9091TRI.eliminateFrameIndex(MI, 0, i, nullptr);92Modified = true;93}94}95}9697// Add function prolog/epilog98TFI.emitPrologue(MF, MF.front());99100for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {101// If last instruction is a return instruction, add an epilogue102if (I->isReturnBlock())103TFI.emitEpilogue(MF, *I);104}105106return Modified;107}108109/// AdjustStackOffset - Helper function used to adjust the stack frame offset.110static inline void AdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx,111bool StackGrowsDown, int64_t &Offset,112Align &MaxAlign) {113// If the stack grows down, add the object size to find the lowest address.114if (StackGrowsDown)115Offset += MFI.getObjectSize(FrameIdx);116117Align Alignment = MFI.getObjectAlign(FrameIdx);118119// If the alignment of this object is greater than that of the stack, then120// increase the stack alignment to match.121MaxAlign = std::max(MaxAlign, Alignment);122123// Adjust to alignment boundary.124Offset = alignTo(Offset, Alignment);125126if (StackGrowsDown) {127LLVM_DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset128<< "]\n");129MFI.setObjectOffset(FrameIdx, -Offset); // Set the computed offset130} else {131LLVM_DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << Offset132<< "]\n");133MFI.setObjectOffset(FrameIdx, Offset);134Offset += MFI.getObjectSize(FrameIdx);135}136}137138void139NVPTXPrologEpilogPass::calculateFrameObjectOffsets(MachineFunction &Fn) {140const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering();141const TargetRegisterInfo *RegInfo = Fn.getSubtarget().getRegisterInfo();142143bool StackGrowsDown =144TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown;145146// Loop over all of the stack objects, assigning sequential addresses...147MachineFrameInfo &MFI = Fn.getFrameInfo();148149// Start at the beginning of the local area.150// The Offset is the distance from the stack top in the direction151// of stack growth -- so it's always nonnegative.152int LocalAreaOffset = TFI.getOffsetOfLocalArea();153if (StackGrowsDown)154LocalAreaOffset = -LocalAreaOffset;155assert(LocalAreaOffset >= 0156&& "Local area offset should be in direction of stack growth");157int64_t Offset = LocalAreaOffset;158159// If there are fixed sized objects that are preallocated in the local area,160// non-fixed objects can't be allocated right at the start of local area.161// We currently don't support filling in holes in between fixed sized162// objects, so we adjust 'Offset' to point to the end of last fixed sized163// preallocated object.164for (int i = MFI.getObjectIndexBegin(); i != 0; ++i) {165int64_t FixedOff;166if (StackGrowsDown) {167// The maximum distance from the stack pointer is at lower address of168// the object -- which is given by offset. For down growing stack169// the offset is negative, so we negate the offset to get the distance.170FixedOff = -MFI.getObjectOffset(i);171} else {172// The maximum distance from the start pointer is at the upper173// address of the object.174FixedOff = MFI.getObjectOffset(i) + MFI.getObjectSize(i);175}176if (FixedOff > Offset) Offset = FixedOff;177}178179// NOTE: We do not have a call stack180181Align MaxAlign = MFI.getMaxAlign();182183// No scavenger184185// FIXME: Once this is working, then enable flag will change to a target186// check for whether the frame is large enough to want to use virtual187// frame index registers. Functions which don't want/need this optimization188// will continue to use the existing code path.189if (MFI.getUseLocalStackAllocationBlock()) {190Align Alignment = MFI.getLocalFrameMaxAlign();191192// Adjust to alignment boundary.193Offset = alignTo(Offset, Alignment);194195LLVM_DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n");196197// Resolve offsets for objects in the local block.198for (unsigned i = 0, e = MFI.getLocalFrameObjectCount(); i != e; ++i) {199std::pair<int, int64_t> Entry = MFI.getLocalFrameObjectMap(i);200int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second;201LLVM_DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" << FIOffset202<< "]\n");203MFI.setObjectOffset(Entry.first, FIOffset);204}205// Allocate the local block206Offset += MFI.getLocalFrameSize();207208MaxAlign = std::max(Alignment, MaxAlign);209}210211// No stack protector212213// Then assign frame offsets to stack objects that are not used to spill214// callee saved registers.215for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) {216if (MFI.isObjectPreAllocated(i) &&217MFI.getUseLocalStackAllocationBlock())218continue;219if (MFI.isDeadObjectIndex(i))220continue;221222AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);223}224225// No scavenger226227if (!TFI.targetHandlesStackFrameRounding()) {228// If we have reserved argument space for call sites in the function229// immediately on entry to the current function, count it as part of the230// overall stack size.231if (MFI.adjustsStack() && TFI.hasReservedCallFrame(Fn))232Offset += MFI.getMaxCallFrameSize();233234// Round up the size to a multiple of the alignment. If the function has235// any calls or alloca's, align to the target's StackAlignment value to236// ensure that the callee's frame or the alloca data is suitably aligned;237// otherwise, for leaf functions, align to the TransientStackAlignment238// value.239Align StackAlign;240if (MFI.adjustsStack() || MFI.hasVarSizedObjects() ||241(RegInfo->hasStackRealignment(Fn) && MFI.getObjectIndexEnd() != 0))242StackAlign = TFI.getStackAlign();243else244StackAlign = TFI.getTransientStackAlign();245246// If the frame pointer is eliminated, all frame offsets will be relative to247// SP not FP. Align to MaxAlign so this works.248Offset = alignTo(Offset, std::max(StackAlign, MaxAlign));249}250251// Update frame info to pretend that this is part of the stack...252int64_t StackSize = Offset - LocalAreaOffset;253MFI.setStackSize(StackSize);254}255256257