1//===--------------------- SIFrameLowering.h --------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIB_TARGET_AMDGPU_SIFRAMELOWERING_H
10#define LLVM_LIB_TARGET_AMDGPU_SIFRAMELOWERING_H
11
12#include "AMDGPUFrameLowering.h"
13#include "SIRegisterInfo.h"
14
15namespace llvm {
16
17class SIInstrInfo;
18
19class SIFrameLowering final : public AMDGPUFrameLowering {
20public:
21 SIFrameLowering(StackDirection D, Align StackAl, int LAO,
22 Align TransAl = Align(1))
23 : AMDGPUFrameLowering(D, StackAl, LAO, TransAl) {}
24 ~SIFrameLowering() override = default;
25
26 void emitEntryFunctionPrologue(MachineFunction &MF,
27 MachineBasicBlock &MBB) const;
28 void emitPrologue(MachineFunction &MF,
29 MachineBasicBlock &MBB) const override;
30 void emitEpilogue(MachineFunction &MF,
31 MachineBasicBlock &MBB) const override;
32 StackOffset getFrameIndexReference(const MachineFunction &MF, int FI,
33 Register &FrameReg) const override;
34
35 void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
36 RegScavenger *RS = nullptr) const override;
37 void determineCalleeSavesSGPR(MachineFunction &MF, BitVector &SavedRegs,
38 RegScavenger *RS = nullptr) const;
39 void determinePrologEpilogSGPRSaves(MachineFunction &MF, BitVector &SavedRegs,
40 bool NeedExecCopyReservedReg) const;
41 void emitCSRSpillStores(MachineFunction &MF, MachineBasicBlock &MBB,
42 MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
43 LiveRegUnits &LiveUnits, Register FrameReg,
44 Register FramePtrRegScratchCopy,
45 const bool NeedsFrameMoves) const;
46 void emitCSRSpillRestores(MachineFunction &MF, MachineBasicBlock &MBB,
47 MachineBasicBlock::iterator MBBI,
48 const DebugLoc &DL, LiveRegUnits &LiveUnits,
49 Register FrameReg,
50 Register FramePtrRegScratchCopy) const;
51 bool
52 assignCalleeSavedSpillSlots(MachineFunction &MF,
53 const TargetRegisterInfo *TRI,
54 std::vector<CalleeSavedInfo> &CSI) const override;
55
56 bool assignCalleeSavedSpillSlotsImpl(MachineFunction &MF,
57 const TargetRegisterInfo *TRI,
58 std::vector<CalleeSavedInfo> &CSI) const;
59
60private:
61 /// Spill a single CSR according to @p CS
62 ///
63 /// This is a separate method so it an be shared between the block-ops enabled
64 /// and disabled paths. Even when block-ops are enabled we may not have a
65 /// viable block for a specific register, so it will fall back to this
66 /// implementation.
67 ///
68 /// @p LiveInRoots conveys whether we are tracking liveness, and if we are
69 /// it captures the original live-ins before spilling in a way that can be
70 /// (relatively) efficiently checked without enumerating all register aliases.
71 /// See @c buildLiveInRoots in the implementation.
72 void spillCalleeSavedRegisterWithoutBlockOps(
73 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
74 const CalleeSavedInfo &CS, const SIInstrInfo *TII,
75 const SIRegisterInfo &TRI,
76 const std::optional<SparseBitVector<>> &LiveInRoots) const;
77
78public:
79 bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
80 MachineBasicBlock::iterator MI,
81 ArrayRef<CalleeSavedInfo> CSI,
82 const TargetRegisterInfo *TRI) const override;
83
84 bool
85 restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
86 MachineBasicBlock::iterator MI,
87 MutableArrayRef<CalleeSavedInfo> CSI,
88 const TargetRegisterInfo *TRI) const override;
89
90 bool allocateScavengingFrameIndexesNearIncomingSP(
91 const MachineFunction &MF) const override;
92
93 bool isSupportedStackID(TargetStackID::Value ID) const override;
94
95 void processFunctionBeforeFrameFinalized(
96 MachineFunction &MF,
97 RegScavenger *RS = nullptr) const override;
98
99 void processFunctionBeforeFrameIndicesReplaced(
100 MachineFunction &MF, RegScavenger *RS = nullptr) const override;
101
102 MachineBasicBlock::iterator
103 eliminateCallFramePseudoInstr(MachineFunction &MF,
104 MachineBasicBlock &MBB,
105 MachineBasicBlock::iterator MI) const override;
106
107protected:
108 bool hasFPImpl(const MachineFunction &MF) const override;
109
110private:
111 void emitEntryFunctionFlatScratchInit(MachineFunction &MF,
112 MachineBasicBlock &MBB,
113 MachineBasicBlock::iterator I,
114 const DebugLoc &DL,
115 Register ScratchWaveOffsetReg) const;
116
117 Register getEntryFunctionReservedScratchRsrcReg(MachineFunction &MF) const;
118
119 void emitEntryFunctionScratchRsrcRegSetup(
120 MachineFunction &MF, MachineBasicBlock &MBB,
121 MachineBasicBlock::iterator I, const DebugLoc &DL,
122 Register PreloadedPrivateBufferReg, Register ScratchRsrcReg,
123 Register ScratchWaveOffsetReg) const;
124
125 void emitPrologueEntryCFI(MachineBasicBlock &MBB,
126 MachineBasicBlock::iterator MBBI,
127 const DebugLoc &DL) const;
128
129 void emitDefCFA(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
130 DebugLoc const &DL, MCRegister StackPtrReg,
131 bool AspaceAlreadyDefined,
132 MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const;
133
134public:
135 bool requiresStackPointerReference(const MachineFunction &MF) const;
136
137 /// Create a CFI index for CFIInst and build a MachineInstr around it.
138 MachineInstr *
139 buildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
140 const DebugLoc &DL, const MCCFIInstruction &CFIInst,
141 MachineInstr::MIFlag flag = MachineInstr::FrameSetup) const;
142
143 /// Create a CFI index describing a spill of the VGPR/AGPR \p Reg to another
144 /// VGPR/AGPR \p RegCopy and build a MachineInstr around it.
145 MachineInstr *buildCFIForVRegToVRegSpill(MachineBasicBlock &MBB,
146 MachineBasicBlock::iterator MBBI,
147 const DebugLoc &DL,
148 const MCRegister Reg,
149 const MCRegister RegCopy) const;
150 /// Create a CFI index describing a spill of an SGPR to a single lane of
151 /// a VGPR and build a MachineInstr around it.
152 MachineInstr *buildCFIForSGPRToVGPRSpill(MachineBasicBlock &MBB,
153 MachineBasicBlock::iterator MBBI,
154 const DebugLoc &DL,
155 const MCRegister SGPR,
156 const MCRegister VGPR,
157 const int Lane) const;
158 /// Create a CFI index describing a spill of an SGPR to multiple lanes of
159 /// VGPRs and build a MachineInstr around it.
160 MachineInstr *buildCFIForSGPRToVGPRSpill(
161 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
162 const DebugLoc &DL, MCRegister SGPR,
163 ArrayRef<SIRegisterInfo::SpilledReg> VGPRSpills) const;
164 /// Create a CFI index describing a spill of a SGPR to VMEM and
165 /// build a MachineInstr around it.
166 MachineInstr *buildCFIForSGPRToVMEMSpill(MachineBasicBlock &MBB,
167 MachineBasicBlock::iterator MBBI,
168 const DebugLoc &DL, MCRegister SGPR,
169 int64_t Offset) const;
170 /// Create a CFI index describing a spill of a VGPR to VMEM and
171 /// build a MachineInstr around it.
172 MachineInstr *buildCFIForVGPRToVMEMSpill(MachineBasicBlock &MBB,
173 MachineBasicBlock::iterator MBBI,
174 const DebugLoc &DL, MCRegister VGPR,
175 int64_t Offset) const;
176 MachineInstr *buildCFIForRegToSGPRPairSpill(MachineBasicBlock &MBB,
177 MachineBasicBlock::iterator MBBI,
178 const DebugLoc &DL,
179 MCRegister Reg,
180 MCRegister SGPRPair) const;
181 MachineInstr *buildCFIForSameValue(MachineBasicBlock &MBB,
182 MachineBasicBlock::iterator MBBI,
183 const DebugLoc &DL, MCRegister Reg) const;
184 // Returns true if the function may need to reserve space on the stack for the
185 // CWSR trap handler.
186 bool mayReserveScratchForCWSR(const MachineFunction &MF) const;
187};
188
189} // end namespace llvm
190
191#endif // LLVM_LIB_TARGET_AMDGPU_SIFRAMELOWERING_H
192