1 //===- GCNRegPressure.h -----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
11 #define LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
13 #include "AMDGPUSubtarget.h"
14 #include "llvm/ADT/DenseMap.h"
15 #include "llvm/CodeGen/LiveIntervals.h"
16 #include "llvm/CodeGen/MachineBasicBlock.h"
17 #include "llvm/CodeGen/MachineInstr.h"
18 #include "llvm/CodeGen/SlotIndexes.h"
19 #include "llvm/MC/LaneBitmask.h"
20 #include "llvm/Support/Debug.h"
26 class MachineRegisterInfo
;
29 struct GCNRegPressure
{
42 bool empty() const { return getSGPRNum() == 0 && getVGPRNum() == 0; }
44 void clear() { std::fill(&Value
[0], &Value
[TOTAL_KINDS
], 0); }
46 unsigned getSGPRNum() const { return Value
[SGPR32
]; }
47 unsigned getVGPRNum() const { return Value
[VGPR32
]; }
49 unsigned getVGPRTuplesWeight() const { return Value
[VGPR_TUPLE
]; }
50 unsigned getSGPRTuplesWeight() const { return Value
[SGPR_TUPLE
]; }
52 unsigned getOccupancy(const GCNSubtarget
&ST
) const {
53 return std::min(ST
.getOccupancyWithNumSGPRs(getSGPRNum()),
54 ST
.getOccupancyWithNumVGPRs(getVGPRNum()));
57 void inc(unsigned Reg
,
60 const MachineRegisterInfo
&MRI
);
62 bool higherOccupancy(const GCNSubtarget
&ST
, const GCNRegPressure
& O
) const {
63 return getOccupancy(ST
) > O
.getOccupancy(ST
);
66 bool less(const GCNSubtarget
&ST
, const GCNRegPressure
& O
,
67 unsigned MaxOccupancy
= std::numeric_limits
<unsigned>::max()) const;
69 bool operator==(const GCNRegPressure
&O
) const {
70 return std::equal(&Value
[0], &Value
[TOTAL_KINDS
], O
.Value
);
73 bool operator!=(const GCNRegPressure
&O
) const {
77 void print(raw_ostream
&OS
, const GCNSubtarget
*ST
= nullptr) const;
78 void dump() const { print(dbgs()); }
81 unsigned Value
[TOTAL_KINDS
];
83 static unsigned getRegKind(unsigned Reg
, const MachineRegisterInfo
&MRI
);
85 friend GCNRegPressure
max(const GCNRegPressure
&P1
,
86 const GCNRegPressure
&P2
);
89 inline GCNRegPressure
max(const GCNRegPressure
&P1
, const GCNRegPressure
&P2
) {
91 for (unsigned I
= 0; I
< GCNRegPressure::TOTAL_KINDS
; ++I
)
92 Res
.Value
[I
] = std::max(P1
.Value
[I
], P2
.Value
[I
]);
98 using LiveRegSet
= DenseMap
<unsigned, LaneBitmask
>;
101 const LiveIntervals
&LIS
;
103 GCNRegPressure CurPressure
, MaxPressure
;
104 const MachineInstr
*LastTrackedMI
= nullptr;
105 mutable const MachineRegisterInfo
*MRI
= nullptr;
107 GCNRPTracker(const LiveIntervals
&LIS_
) : LIS(LIS_
) {}
109 void reset(const MachineInstr
&MI
, const LiveRegSet
*LiveRegsCopy
,
113 // live regs for the current state
114 const decltype(LiveRegs
) &getLiveRegs() const { return LiveRegs
; }
115 const MachineInstr
*getLastTrackedMI() const { return LastTrackedMI
; }
117 void clearMaxPressure() { MaxPressure
.clear(); }
119 // returns MaxPressure, resetting it
120 decltype(MaxPressure
) moveMaxPressure() {
121 auto Res
= MaxPressure
;
126 decltype(LiveRegs
) moveLiveRegs() {
127 return std::move(LiveRegs
);
130 static void printLiveRegs(raw_ostream
&OS
, const LiveRegSet
& LiveRegs
,
131 const MachineRegisterInfo
&MRI
);
134 class GCNUpwardRPTracker
: public GCNRPTracker
{
136 GCNUpwardRPTracker(const LiveIntervals
&LIS_
) : GCNRPTracker(LIS_
) {}
138 // reset tracker to the point just below MI
139 // filling live regs upon this point using LIS
140 void reset(const MachineInstr
&MI
, const LiveRegSet
*LiveRegs
= nullptr);
142 // move to the state just above the MI
143 void recede(const MachineInstr
&MI
);
145 // checks whether the tracker's state after receding MI corresponds
146 // to reported by LIS
147 bool isValid() const;
150 class GCNDownwardRPTracker
: public GCNRPTracker
{
151 // Last position of reset or advanceBeforeNext
152 MachineBasicBlock::const_iterator NextMI
;
154 MachineBasicBlock::const_iterator MBBEnd
;
157 GCNDownwardRPTracker(const LiveIntervals
&LIS_
) : GCNRPTracker(LIS_
) {}
159 const MachineBasicBlock::const_iterator
getNext() const { return NextMI
; }
161 // Reset tracker to the point before the MI
162 // filling live regs upon this point using LIS.
163 // Returns false if block is empty except debug values.
164 bool reset(const MachineInstr
&MI
, const LiveRegSet
*LiveRegs
= nullptr);
166 // Move to the state right before the next MI. Returns false if reached
168 bool advanceBeforeNext();
170 // Move to the state at the MI, advanceBeforeNext has to be called first.
171 void advanceToNext();
173 // Move to the state at the next MI. Returns false if reached end of block.
176 // Advance instructions until before End.
177 bool advance(MachineBasicBlock::const_iterator End
);
179 // Reset to Begin and advance to End.
180 bool advance(MachineBasicBlock::const_iterator Begin
,
181 MachineBasicBlock::const_iterator End
,
182 const LiveRegSet
*LiveRegsCopy
= nullptr);
185 LaneBitmask
getLiveLaneMask(unsigned Reg
,
187 const LiveIntervals
&LIS
,
188 const MachineRegisterInfo
&MRI
);
190 GCNRPTracker::LiveRegSet
getLiveRegs(SlotIndex SI
,
191 const LiveIntervals
&LIS
,
192 const MachineRegisterInfo
&MRI
);
194 inline GCNRPTracker::LiveRegSet
getLiveRegsAfter(const MachineInstr
&MI
,
195 const LiveIntervals
&LIS
) {
196 return getLiveRegs(LIS
.getInstructionIndex(MI
).getDeadSlot(), LIS
,
197 MI
.getParent()->getParent()->getRegInfo());
200 inline GCNRPTracker::LiveRegSet
getLiveRegsBefore(const MachineInstr
&MI
,
201 const LiveIntervals
&LIS
) {
202 return getLiveRegs(LIS
.getInstructionIndex(MI
).getBaseIndex(), LIS
,
203 MI
.getParent()->getParent()->getRegInfo());
206 template <typename Range
>
207 GCNRegPressure
getRegPressure(const MachineRegisterInfo
&MRI
,
210 for (const auto &RM
: LiveRegs
)
211 Res
.inc(RM
.first
, LaneBitmask::getNone(), RM
.second
, MRI
);
215 void printLivesAt(SlotIndex SI
,
216 const LiveIntervals
&LIS
,
217 const MachineRegisterInfo
&MRI
);
219 } // end namespace llvm
221 #endif // LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H