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