blob: 38bf3fee0cf7ba2bd30217b973c5a6dcfaf6321b [file]
//===--------------------- SIFrameLowering.h --------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_AMDGPU_SIFRAMELOWERING_H
#define LLVM_LIB_TARGET_AMDGPU_SIFRAMELOWERING_H
#include "AMDGPUFrameLowering.h"
#include "SIRegisterInfo.h"
namespace llvm {
class SIInstrInfo;
class SIFrameLowering final : public AMDGPUFrameLowering {
public:
SIFrameLowering(StackDirection D, Align StackAl, int LAO,
Align TransAl = Align(1))
: AMDGPUFrameLowering(D, StackAl, LAO, TransAl) {}
~SIFrameLowering() override = default;
void emitEntryFunctionPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const;
void emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const override;
void emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const override;
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI,
Register &FrameReg) const override;
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
RegScavenger *RS = nullptr) const override;
void determineCalleeSavesSGPR(MachineFunction &MF, BitVector &SavedRegs,
RegScavenger *RS = nullptr) const;
void determinePrologEpilogSGPRSaves(MachineFunction &MF, BitVector &SavedRegs,
bool NeedExecCopyReservedReg) const;
void emitCSRSpillStores(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
LiveRegUnits &LiveUnits, Register FrameReg,
Register FramePtrRegScratchCopy,
const bool NeedsFrameMoves) const;
void emitCSRSpillRestores(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, LiveRegUnits &LiveUnits,
Register FrameReg,
Register FramePtrRegScratchCopy) const;
bool
assignCalleeSavedSpillSlots(MachineFunction &MF,
const TargetRegisterInfo *TRI,
std::vector<CalleeSavedInfo> &CSI) const override;
bool assignCalleeSavedSpillSlotsImpl(MachineFunction &MF,
const TargetRegisterInfo *TRI,
std::vector<CalleeSavedInfo> &CSI) const;
private:
/// Spill a single CSR according to @p CS
///
/// This is a separate method so it an be shared between the block-ops enabled
/// and disabled paths. Even when block-ops are enabled we may not have a
/// viable block for a specific register, so it will fall back to this
/// implementation.
///
/// @p LiveInRoots conveys whether we are tracking liveness, and if we are
/// it captures the original live-ins before spilling in a way that can be
/// (relatively) efficiently checked without enumerating all register aliases.
/// See @c buildLiveInRoots in the implementation.
void spillCalleeSavedRegisterWithoutBlockOps(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
const CalleeSavedInfo &CS, const SIInstrInfo *TII,
const SIRegisterInfo &TRI,
const std::optional<SparseBitVector<>> &LiveInRoots) const;
public:
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
ArrayRef<CalleeSavedInfo> CSI,
const TargetRegisterInfo *TRI) const override;
bool
restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
MutableArrayRef<CalleeSavedInfo> CSI,
const TargetRegisterInfo *TRI) const override;
bool allocateScavengingFrameIndexesNearIncomingSP(
const MachineFunction &MF) const override;
bool isSupportedStackID(TargetStackID::Value ID) const override;
void processFunctionBeforeFrameFinalized(
MachineFunction &MF,
RegScavenger *RS = nullptr) const override;
void processFunctionBeforeFrameIndicesReplaced(
MachineFunction &MF, RegScavenger *RS = nullptr) const override;
MachineBasicBlock::iterator
eliminateCallFramePseudoInstr(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI) const override;
protected:
bool hasFPImpl(const MachineFunction &MF) const override;
private:
void emitEntryFunctionFlatScratchInit(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
const DebugLoc &DL,
Register ScratchWaveOffsetReg) const;
Register getEntryFunctionReservedScratchRsrcReg(MachineFunction &MF) const;
void emitEntryFunctionScratchRsrcRegSetup(
MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I, const DebugLoc &DL,
Register PreloadedPrivateBufferReg, Register ScratchRsrcReg,
Register ScratchWaveOffsetReg) const;
void emitPrologueEntryCFI(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL) const;
void emitDefCFA(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
DebugLoc const &DL, MCRegister StackPtrReg,
bool AspaceAlreadyDefined,
MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const;
public:
bool requiresStackPointerReference(const MachineFunction &MF) const;
/// Create a CFI index for CFIInst and build a MachineInstr around it.
MachineInstr *
buildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, const MCCFIInstruction &CFIInst,
MachineInstr::MIFlag flag = MachineInstr::FrameSetup) const;
/// Create a CFI index describing a spill of the VGPR/AGPR \p Reg to another
/// VGPR/AGPR \p RegCopy and build a MachineInstr around it.
MachineInstr *buildCFIForVRegToVRegSpill(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL,
const MCRegister Reg,
const MCRegister RegCopy) const;
/// Create a CFI index describing a spill of an SGPR to a single lane of
/// a VGPR and build a MachineInstr around it.
MachineInstr *buildCFIForSGPRToVGPRSpill(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL,
const MCRegister SGPR,
const MCRegister VGPR,
const int Lane) const;
/// Create a CFI index describing a spill of an SGPR to multiple lanes of
/// VGPRs and build a MachineInstr around it.
MachineInstr *buildCFIForSGPRToVGPRSpill(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, MCRegister SGPR,
ArrayRef<SIRegisterInfo::SpilledReg> VGPRSpills) const;
/// Create a CFI index describing a spill of a SGPR to VMEM and
/// build a MachineInstr around it.
MachineInstr *buildCFIForSGPRToVMEMSpill(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, MCRegister SGPR,
int64_t Offset) const;
/// Create a CFI index describing a spill of a VGPR to VMEM and
/// build a MachineInstr around it.
MachineInstr *buildCFIForVGPRToVMEMSpill(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, MCRegister VGPR,
int64_t Offset) const;
MachineInstr *buildCFIForRegToSGPRPairSpill(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL,
MCRegister Reg,
MCRegister SGPRPair) const;
MachineInstr *buildCFIForSameValue(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, MCRegister Reg) const;
// Returns true if the function may need to reserve space on the stack for the
// CWSR trap handler.
bool mayReserveScratchForCWSR(const MachineFunction &MF) const;
};
} // end namespace llvm
#endif // LLVM_LIB_TARGET_AMDGPU_SIFRAMELOWERING_H