[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / AMDGPU / GCNRegPressure.h
blob257561cb8430f17c4cec836ee717f1e63fd658be
1 //===- GCNRegPressure.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 /// \file
10 /// This file defines the GCNRegPressure class, which tracks registry pressure
11 /// by bookkeeping number of SGPR/VGPRs used, weights for large SGPR/VGPRs. It
12 /// also implements a compare function, which compares different register
13 /// pressures, and declares one with max occupance as winner.
14 ///
15 //===----------------------------------------------------------------------===//
17 #ifndef LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
18 #define LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
20 #include "GCNSubtarget.h"
21 #include "llvm/CodeGen/LiveIntervals.h"
22 #include <algorithm>
24 namespace llvm {
26 class MachineRegisterInfo;
27 class raw_ostream;
28 class SlotIndex;
30 struct GCNRegPressure {
31 enum RegKind {
32 SGPR32,
33 SGPR_TUPLE,
34 VGPR32,
35 VGPR_TUPLE,
36 AGPR32,
37 AGPR_TUPLE,
38 TOTAL_KINDS
41 GCNRegPressure() {
42 clear();
45 bool empty() const { return getSGPRNum() == 0 && getVGPRNum(false) == 0; }
47 void clear() { std::fill(&Value[0], &Value[TOTAL_KINDS], 0); }
49 unsigned getSGPRNum() const { return Value[SGPR32]; }
50 unsigned getVGPRNum(bool UnifiedVGPRFile) const {
51 if (UnifiedVGPRFile) {
52 return Value[AGPR32] ? alignTo(Value[VGPR32], 4) + Value[AGPR32]
53 : Value[VGPR32] + Value[AGPR32];
55 return std::max(Value[VGPR32], Value[AGPR32]);
57 unsigned getAGPRNum() const { return Value[AGPR32]; }
59 unsigned getVGPRTuplesWeight() const { return std::max(Value[VGPR_TUPLE],
60 Value[AGPR_TUPLE]); }
61 unsigned getSGPRTuplesWeight() const { return Value[SGPR_TUPLE]; }
63 unsigned getOccupancy(const GCNSubtarget &ST) const {
64 return std::min(ST.getOccupancyWithNumSGPRs(getSGPRNum()),
65 ST.getOccupancyWithNumVGPRs(getVGPRNum(ST.hasGFX90AInsts())));
68 void inc(unsigned Reg,
69 LaneBitmask PrevMask,
70 LaneBitmask NewMask,
71 const MachineRegisterInfo &MRI);
73 bool higherOccupancy(const GCNSubtarget &ST, const GCNRegPressure& O) const {
74 return getOccupancy(ST) > O.getOccupancy(ST);
77 bool less(const GCNSubtarget &ST, const GCNRegPressure& O,
78 unsigned MaxOccupancy = std::numeric_limits<unsigned>::max()) const;
80 bool operator==(const GCNRegPressure &O) const {
81 return std::equal(&Value[0], &Value[TOTAL_KINDS], O.Value);
84 bool operator!=(const GCNRegPressure &O) const {
85 return !(*this == O);
88 void print(raw_ostream &OS, const GCNSubtarget *ST = nullptr) const;
89 void dump() const { print(dbgs()); }
91 private:
92 unsigned Value[TOTAL_KINDS];
94 static unsigned getRegKind(Register Reg, const MachineRegisterInfo &MRI);
96 friend GCNRegPressure max(const GCNRegPressure &P1,
97 const GCNRegPressure &P2);
100 inline GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2) {
101 GCNRegPressure Res;
102 for (unsigned I = 0; I < GCNRegPressure::TOTAL_KINDS; ++I)
103 Res.Value[I] = std::max(P1.Value[I], P2.Value[I]);
104 return Res;
107 class GCNRPTracker {
108 public:
109 using LiveRegSet = DenseMap<unsigned, LaneBitmask>;
111 protected:
112 const LiveIntervals &LIS;
113 LiveRegSet LiveRegs;
114 GCNRegPressure CurPressure, MaxPressure;
115 const MachineInstr *LastTrackedMI = nullptr;
116 mutable const MachineRegisterInfo *MRI = nullptr;
118 GCNRPTracker(const LiveIntervals &LIS_) : LIS(LIS_) {}
120 void reset(const MachineInstr &MI, const LiveRegSet *LiveRegsCopy,
121 bool After);
123 public:
124 // live regs for the current state
125 const decltype(LiveRegs) &getLiveRegs() const { return LiveRegs; }
126 const MachineInstr *getLastTrackedMI() const { return LastTrackedMI; }
128 void clearMaxPressure() { MaxPressure.clear(); }
130 // returns MaxPressure, resetting it
131 decltype(MaxPressure) moveMaxPressure() {
132 auto Res = MaxPressure;
133 MaxPressure.clear();
134 return Res;
137 decltype(LiveRegs) moveLiveRegs() {
138 return std::move(LiveRegs);
141 static void printLiveRegs(raw_ostream &OS, const LiveRegSet& LiveRegs,
142 const MachineRegisterInfo &MRI);
145 class GCNUpwardRPTracker : public GCNRPTracker {
146 public:
147 GCNUpwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
149 // reset tracker to the point just below MI
150 // filling live regs upon this point using LIS
151 void reset(const MachineInstr &MI, const LiveRegSet *LiveRegs = nullptr);
153 // move to the state just above the MI
154 void recede(const MachineInstr &MI);
156 // checks whether the tracker's state after receding MI corresponds
157 // to reported by LIS
158 bool isValid() const;
161 class GCNDownwardRPTracker : public GCNRPTracker {
162 // Last position of reset or advanceBeforeNext
163 MachineBasicBlock::const_iterator NextMI;
165 MachineBasicBlock::const_iterator MBBEnd;
167 public:
168 GCNDownwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
170 MachineBasicBlock::const_iterator getNext() const { return NextMI; }
172 // Reset tracker to the point before the MI
173 // filling live regs upon this point using LIS.
174 // Returns false if block is empty except debug values.
175 bool reset(const MachineInstr &MI, const LiveRegSet *LiveRegs = nullptr);
177 // Move to the state right before the next MI. Returns false if reached
178 // end of the block.
179 bool advanceBeforeNext();
181 // Move to the state at the MI, advanceBeforeNext has to be called first.
182 void advanceToNext();
184 // Move to the state at the next MI. Returns false if reached end of block.
185 bool advance();
187 // Advance instructions until before End.
188 bool advance(MachineBasicBlock::const_iterator End);
190 // Reset to Begin and advance to End.
191 bool advance(MachineBasicBlock::const_iterator Begin,
192 MachineBasicBlock::const_iterator End,
193 const LiveRegSet *LiveRegsCopy = nullptr);
196 LaneBitmask getLiveLaneMask(unsigned Reg,
197 SlotIndex SI,
198 const LiveIntervals &LIS,
199 const MachineRegisterInfo &MRI);
201 GCNRPTracker::LiveRegSet getLiveRegs(SlotIndex SI,
202 const LiveIntervals &LIS,
203 const MachineRegisterInfo &MRI);
205 /// creates a map MachineInstr -> LiveRegSet
206 /// R - range of iterators on instructions
207 /// After - upon entry or exit of every instruction
208 /// Note: there is no entry in the map for instructions with empty live reg set
209 /// Complexity = O(NumVirtRegs * averageLiveRangeSegmentsPerReg * lg(R))
210 template <typename Range>
211 DenseMap<MachineInstr*, GCNRPTracker::LiveRegSet>
212 getLiveRegMap(Range &&R, bool After, LiveIntervals &LIS) {
213 std::vector<SlotIndex> Indexes;
214 Indexes.reserve(std::distance(R.begin(), R.end()));
215 auto &SII = *LIS.getSlotIndexes();
216 for (MachineInstr *I : R) {
217 auto SI = SII.getInstructionIndex(*I);
218 Indexes.push_back(After ? SI.getDeadSlot() : SI.getBaseIndex());
220 llvm::sort(Indexes);
222 auto &MRI = (*R.begin())->getParent()->getParent()->getRegInfo();
223 DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> LiveRegMap;
224 SmallVector<SlotIndex, 32> LiveIdxs, SRLiveIdxs;
225 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
226 auto Reg = Register::index2VirtReg(I);
227 if (!LIS.hasInterval(Reg))
228 continue;
229 auto &LI = LIS.getInterval(Reg);
230 LiveIdxs.clear();
231 if (!LI.findIndexesLiveAt(Indexes, std::back_inserter(LiveIdxs)))
232 continue;
233 if (!LI.hasSubRanges()) {
234 for (auto SI : LiveIdxs)
235 LiveRegMap[SII.getInstructionFromIndex(SI)][Reg] =
236 MRI.getMaxLaneMaskForVReg(Reg);
237 } else
238 for (const auto &S : LI.subranges()) {
239 // constrain search for subranges by indexes live at main range
240 SRLiveIdxs.clear();
241 S.findIndexesLiveAt(LiveIdxs, std::back_inserter(SRLiveIdxs));
242 for (auto SI : SRLiveIdxs)
243 LiveRegMap[SII.getInstructionFromIndex(SI)][Reg] |= S.LaneMask;
246 return LiveRegMap;
249 inline GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI,
250 const LiveIntervals &LIS) {
251 return getLiveRegs(LIS.getInstructionIndex(MI).getDeadSlot(), LIS,
252 MI.getParent()->getParent()->getRegInfo());
255 inline GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI,
256 const LiveIntervals &LIS) {
257 return getLiveRegs(LIS.getInstructionIndex(MI).getBaseIndex(), LIS,
258 MI.getParent()->getParent()->getRegInfo());
261 template <typename Range>
262 GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI,
263 Range &&LiveRegs) {
264 GCNRegPressure Res;
265 for (const auto &RM : LiveRegs)
266 Res.inc(RM.first, LaneBitmask::getNone(), RM.second, MRI);
267 return Res;
270 bool isEqual(const GCNRPTracker::LiveRegSet &S1,
271 const GCNRPTracker::LiveRegSet &S2);
273 void printLivesAt(SlotIndex SI,
274 const LiveIntervals &LIS,
275 const MachineRegisterInfo &MRI);
277 } // end namespace llvm
279 #endif // LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H