LLVM 24.0.0git
AMDGPUNextUseAnalysis.h
Go to the documentation of this file.
1//===---------------------- AMDGPUNextUseAnalysis.h ----------------------===//
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// This file implements Next Use Analysis.
10//
11// For each register it goes over all uses and returns the estimated distance of
12// the nearest use. This will be used for selecting which registers to spill
13// before register allocation.
14//
15// This is based on ideas from the paper:
16// "Register Spilling and Live-Range Splitting for SSA-Form Programs"
17// Matthias Braun and Sebastian Hack, CC'09
18//
19//===----------------------------------------------------------------------===//
20
21#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUNEXTUSEANALYSIS_H
22#define LLVM_LIB_TARGET_AMDGPU_AMDGPUNEXTUSEANALYSIS_H
23
24#include "SIInstrInfo.h"
25#include "SIRegisterInfo.h"
30#include "llvm/IR/PassManager.h"
31#include "llvm/Support/Format.h"
32#include "llvm/Support/JSON.h"
33#include <limits>
34#include <optional>
35
36namespace llvm {
37
39
40//==============================================================================
41// NextUseDistance - Represents a distance in the next-use analysis. Currently
42// wraps a 64-bit int with special encoding for loop depth and unreachable
43// distances.
44//==============================================================================
46public:
47 constexpr static NextUseDistance unreachable() {
48 return NextUseDistance(std::numeric_limits<int64_t>::max());
49 }
50
51 constexpr static NextUseDistance fromSize(unsigned Size, unsigned Depth) {
53 }
54
55 constexpr NextUseDistance(unsigned V) : Value(V) {}
56 constexpr NextUseDistance(int V) : Value(V) {}
57 constexpr NextUseDistance(const NextUseDistance &B) : Value(B.Value) {}
58
59 constexpr bool isUnreachable() const { return *this == unreachable(); }
60 constexpr bool isReachable() const { return !isUnreachable(); }
61
62 //----------------------------------------------------------------------------
63 // Assignment
64 //----------------------------------------------------------------------------
66 Value = B.Value;
67 return *this;
68 }
69
70 constexpr NextUseDistance &operator=(unsigned V) {
71 Value = V;
72 return *this;
73 }
74
75 constexpr NextUseDistance &operator=(int V) {
76 Value = V;
77 return *this;
78 }
79
80 //----------------------------------------------------------------------------
81 // Arithmetic operators
82 //----------------------------------------------------------------------------
84 Value += B.Value;
85 return *this;
86 }
87
89 Value -= B.Value;
90 return *this;
91 }
92
93 constexpr NextUseDistance operator-() const {
94 return NextUseDistance(-Value);
95 }
96
97 constexpr NextUseDistance applyLoopWeight() const {
98 NextUseDistance W = fromLoopDepth(1);
99 if (W.isUnreachable())
100 return unreachable();
101 constexpr int64_t MaxVal = std::numeric_limits<int64_t>::max();
102 if (Value != 0 && W.Value > MaxVal / Value)
103 return unreachable();
104 return NextUseDistance(Value * W.Value);
105 }
106
107 //----------------------------------------------------------------------------
108 // Comparison operators
109 //----------------------------------------------------------------------------
110 constexpr bool operator<(const NextUseDistance &B) const {
111 return Value < B.Value;
112 }
113
114 constexpr bool operator>(const NextUseDistance &B) const {
115 return Value > B.Value;
116 }
117
118 constexpr bool operator<=(const NextUseDistance &B) const {
119 return Value <= B.Value;
120 }
121
122 constexpr bool operator>=(const NextUseDistance &B) const {
123 return Value >= B.Value;
124 }
125
126 constexpr bool operator==(const NextUseDistance &B) const {
127 return Value == B.Value;
128 }
129
130 constexpr bool operator!=(const NextUseDistance &B) const {
131 return Value != B.Value;
132 }
133
134 //----------------------------------------------------------------------------
135 // Debugging
136 //----------------------------------------------------------------------------
137 format_object<int64_t> fmt() const { return format("%ld", Value); }
138
139 void print(raw_ostream &OS) const {
140 if (isUnreachable())
141 OS << "<unreachable>";
142 else
143 OS << fmt();
144 }
145
147 if (isUnreachable())
148 return "<unreachable>";
149 return Value;
150 }
151
152 std::string toString() const {
153 std::string Str;
155 print(OS);
156 return OS.str();
157 }
158
159 constexpr int64_t getRawValue() const { return Value; }
160 using RawValueType = int64_t;
161
162private:
164 int64_t Value;
165 constexpr explicit NextUseDistance(int64_t V) : Value(V) {}
166
167 constexpr static NextUseDistance fromLoopDepth(unsigned Depth) {
168 const unsigned Shift = 7 * Depth;
169
170 // Saturate?
171 if (Shift >= 63)
172 return unreachable();
173
174 // This implementation is multiplicative (f(a+b) == f(a) * f(b)) which we
175 // take advantage of below in applyLoopWeight(Depth).
176 return NextUseDistance(int64_t(1) << Shift);
177 }
178
179 // Semantically: apply fromLoopDepth(1) Depth times (compositional).
180 //
181 // Optimized to take advantage of multiplicative implementation of
182 // fromLoopDepth - a single multiply by fromLoopDepth(Depth) gives the same
183 // result. If fromLoopDepth is changed to a non-multiplicative formula,
184 // replace the body with something like:
185 //
186 // NextUseDistance D = *this;
187 // for (unsigned I = 0; I < Depth; ++I) {
188 // D = D.applyLoopWeight();
189 // if (D.isUnreachable())
190 // return unreachable();
191 // }
192 // return D;
193 //
194 constexpr NextUseDistance applyLoopWeight(unsigned Depth) const {
195 if (!Depth)
196 return *this;
197 NextUseDistance W = fromLoopDepth(Depth);
198 if (W.isUnreachable())
199 return unreachable();
200 constexpr int64_t MaxVal = std::numeric_limits<int64_t>::max();
201 if (Value != 0 && W.Value > MaxVal / Value)
202 return unreachable();
203 return NextUseDistance(Value * W.Value);
204 }
205};
206
208 const NextUseDistance &B) {
209 return A += B;
210}
211
213 const NextUseDistance &B) {
214 return A -= B;
215}
216
218 return A < B ? A : B;
219}
220
222 return A > B ? A : B;
223}
224
225//==============================================================================
226// AMDGPUNextUseAnalysis - Provides next-use distances for live registers or
227// sub-registers at a given MachineInstruction suitable for making spilling
228// decisions.
229//==============================================================================
230class AMDGPUNextUseAnalysis {
235
236 std::unique_ptr<AMDGPUNextUseAnalysisImpl> Impl;
237
238 AMDGPUNextUseAnalysis(const MachineFunction *, const MachineLoopInfo *);
239
240public:
241 AMDGPUNextUseAnalysis(AMDGPUNextUseAnalysis &&Other);
243
244 AMDGPUNextUseAnalysis &operator=(AMDGPUNextUseAnalysis &&Other);
245
246 // Configuration flags for controlling the distance model. Defaults correspond
247 // to the Graphics preset.
248 struct Config {
249 // Count PHI instructions as having non-zero cost (distance and block
250 // size). When false, all PHIs share ID 0 and don't contribute to block
251 // size.
252 bool CountPhis = true;
253
254 // Restrict inter-block distances to forward-reachable paths only.
255 // When false, distances through back-edges are also considered.
256 bool ForwardOnly = true;
257
258 // Model PHI uses as belonging to their incoming edge's block, and apply
259 // full loop-aware reachability filtering including intermediate-def
260 // checks. When false, a simple same-block / forward-reachable check is
261 // used.
262 bool PreciseUseModeling = false;
263
264 // Promote uses that are inside a loop not yet entered or inside a directly
265 // nested inner loop to the end of that loop's preheader. This models the
266 // assumption that a spilled value will be reloaded at the preheader rather
267 // than at the actual use site. When false, direct shortest distance to the
268 // use is used instead.
269 bool PromoteToPreheader = false;
270
271 /// Named presets. See note in AMDGPUNextUseAnalysis.cpp associated with
272 /// 'amdgpu-next-use-analysis-config' regarding the historical context for
273 /// these.
274 static Config Graphics() { return {}; }
275 static Config Compute() {
276 Config Cfg;
277 Cfg.CountPhis = false;
278 Cfg.ForwardOnly = false;
279 Cfg.PreciseUseModeling = true;
280 Cfg.PromoteToPreheader = true;
281 return Cfg;
282 }
283 };
284
285 Config getConfig() const;
286 void setConfig(Config);
287
288 void getReachableUses(Register LiveReg, LaneBitmask LaneMask,
289 const MachineInstr &MI,
291
292 /// \Returns the shortest next-use distance from \p CurMI for \p LiveReg.
294 getShortestDistance(Register LiveReg, const MachineInstr &CurMI,
296 const MachineOperand **ShortestUseOut = nullptr,
297 SmallVector<NextUseDistance> *Distances = nullptr) const;
298
306
308 const MachineInstr &MI, UseDistancePair &Furthest,
309 UseDistancePair *FurthestSubreg = nullptr,
311 *RelevantUses = nullptr) const;
312};
313
314//==============================================================================
315// AMDGPUNextUseAnalysisLegacyPass - Legacy and New pass wrapper around
316// AMDGPUNextUseAnalysis
317//==============================================================================
319
320public:
321 static char ID;
322
324
326 const AMDGPUNextUseAnalysis &getNextUseAnalysis() const { return *NUA; }
327 StringRef getPassName() const override;
328
329protected:
330 bool runOnMachineFunction(MachineFunction &) override;
331 void getAnalysisUsage(AnalysisUsage &AU) const override;
332
333private:
334 std::unique_ptr<AMDGPUNextUseAnalysis> NUA;
335};
336
338 : public AnalysisInfoMixin<AMDGPUNextUseAnalysisPass> {
340 static AnalysisKey Key;
341
342public:
345};
346
347//==============================================================================
348// AMDGPUNextUseAnalysisPrinterLegacyPass - Legacy Pass for printing
349// AMDGPUNextUseAnalysis results as JSON.
350//==============================================================================
352
353public:
354 static char ID;
355
357
358 StringRef getPassName() const override;
359
360protected:
361 bool runOnMachineFunction(MachineFunction &) override;
362 void getAnalysisUsage(AnalysisUsage &AU) const override;
363};
364
366 : public RequiredPassInfoMixin<AMDGPUNextUseAnalysisPrinterPass> {
367 raw_ostream &OS;
368
369public:
373};
374
375} // namespace llvm
376#endif // LLVM_LIB_TARGET_AMDGPU_AMDGPUNEXTUSEANALYSIS_H
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
IRTranslator LLVM IR MI
This header defines various interfaces for pass management in LLVM.
This file supports working with JSON data.
Remove Loads Into Fake Uses
Interface definition for SIInstrInfo.
Interface definition for SIRegisterInfo.
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
bool runOnMachineFunction(MachineFunction &) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
const AMDGPUNextUseAnalysis & getNextUseAnalysis() const
Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
bool runOnMachineFunction(MachineFunction &) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
void getReachableUses(Register LiveReg, LaneBitmask LaneMask, const MachineInstr &MI, SmallVector< const MachineOperand * > &Uses) const
void getNextUseDistances(const DenseMap< unsigned, LaneBitmask > &LiveRegs, const MachineInstr &MI, UseDistancePair &Furthest, UseDistancePair *FurthestSubreg=nullptr, DenseMap< const MachineOperand *, UseDistancePair > *RelevantUses=nullptr) const
NextUseDistance getShortestDistance(Register LiveReg, const MachineInstr &CurMI, const SmallVector< const MachineOperand * > &Uses, const MachineOperand **ShortestUseOut=nullptr, SmallVector< NextUseDistance > *Distances=nullptr) const
\Returns the shortest next-use distance from CurMI for LiveReg.
AMDGPUNextUseAnalysis & operator=(AMDGPUNextUseAnalysis &&Other)
Represent the analysis usage information of a pass.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
constexpr bool operator==(const NextUseDistance &B) const
constexpr bool operator!=(const NextUseDistance &B) const
json::Value toJsonValue() const
constexpr NextUseDistance & operator-=(const NextUseDistance &B)
std::string toString() const
constexpr NextUseDistance & operator=(const NextUseDistance &B)
constexpr NextUseDistance & operator+=(const NextUseDistance &B)
constexpr NextUseDistance(int V)
constexpr bool operator>(const NextUseDistance &B) const
static constexpr NextUseDistance fromSize(unsigned Size, unsigned Depth)
constexpr int64_t getRawValue() const
static constexpr NextUseDistance unreachable()
constexpr bool operator>=(const NextUseDistance &B) const
constexpr NextUseDistance(const NextUseDistance &B)
constexpr bool operator<(const NextUseDistance &B) const
constexpr NextUseDistance & operator=(int V)
constexpr NextUseDistance operator-() const
constexpr bool isReachable() const
void print(raw_ostream &OS) const
constexpr NextUseDistance applyLoopWeight() const
constexpr NextUseDistance(unsigned V)
format_object< int64_t > fmt() const
constexpr NextUseDistance & operator=(unsigned V)
constexpr bool operator<=(const NextUseDistance &B) const
constexpr bool isUnreachable() const
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
A Value is an JSON value of unknown type.
Definition JSON.h:291
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
This is an optimization pass for GlobalISel generic memory operations.
constexpr NextUseDistance min(NextUseDistance A, NextUseDistance B)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:102
@ Other
Any other memory.
Definition ModRef.h:68
constexpr NextUseDistance max(NextUseDistance A, NextUseDistance B)
APInt operator-(APInt)
Definition APInt.h:2214
APInt operator+(APInt a, const APInt &b)
Definition APInt.h:2219
static Config Graphics()
Named presets.
UseDistancePair(const MachineOperand *Use, NextUseDistance Dist)
A CRTP mix-in that provides informational APIs needed for analysis passes.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29
A CRTP mix-in for passes that should not be skipped.