LLVM 20.0.0git
MachineOutliner.h
Go to the documentation of this file.
1//===---- MachineOutliner.h - Outliner data structures ------*- 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/// Contains all data structures shared between the outliner implemented in
11/// MachineOutliner.cpp and target implementations of the outliner.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CODEGEN_MACHINEOUTLINER_H
16#define LLVM_CODEGEN_MACHINEOUTLINER_H
17
22#include <initializer_list>
23
24namespace llvm {
25namespace outliner {
26
27/// Represents how an instruction should be mapped by the outliner.
28/// \p Legal instructions are those which are safe to outline.
29/// \p LegalTerminator instructions are safe to outline, but only as the
30/// last instruction in a sequence.
31/// \p Illegal instructions are those which cannot be outlined.
32/// \p Invisible instructions are instructions which can be outlined, but
33/// shouldn't actually impact the outlining result.
35
36/// An individual sequence of instructions to be replaced with a call to
37/// an outlined function.
38struct Candidate {
39private:
40 /// The start index of this \p Candidate in the instruction list.
41 unsigned StartIdx = 0;
42
43 /// The number of instructions in this \p Candidate.
44 unsigned Len = 0;
45
46 // The first instruction in this \p Candidate.
48
49 // The last instruction in this \p Candidate.
51
52 // The basic block that contains this Candidate.
53 MachineBasicBlock *MBB = nullptr;
54
55 /// Cost of calling an outlined function from this point as defined by the
56 /// target.
57 unsigned CallOverhead = 0;
58
59 /// Liveness information for this Candidate. Tracks from the end of the
60 /// block containing this Candidate to the beginning of its sequence.
61 ///
62 /// Optional. Can be used to fine-tune the cost model, or fine-tune legality
63 /// decisions.
64 LiveRegUnits FromEndOfBlockToStartOfSeq;
65
66 /// Liveness information restricted to this Candidate's instruction sequence.
67 ///
68 /// Optional. Can be used to fine-tune the cost model, or fine-tune legality
69 /// decisions.
70 LiveRegUnits InSeq;
71
72 /// True if FromEndOfBlockToStartOfSeq has been initialized.
73 bool FromEndOfBlockToStartOfSeqWasSet = false;
74
75 /// True if InSeq has been initialized.
76 bool InSeqWasSet = false;
77
78 /// Populate FromEndOfBlockToStartOfSeq with liveness information.
79 void initFromEndOfBlockToStartOfSeq(const TargetRegisterInfo &TRI) {
80 assert(MBB->getParent()->getRegInfo().tracksLiveness() &&
81 "Candidate's Machine Function must track liveness");
82 // Only initialize once.
83 if (FromEndOfBlockToStartOfSeqWasSet)
84 return;
85 FromEndOfBlockToStartOfSeqWasSet = true;
86 FromEndOfBlockToStartOfSeq.init(TRI);
87 FromEndOfBlockToStartOfSeq.addLiveOuts(*MBB);
88 // Compute liveness from the end of the block up to the beginning of the
89 // outlining candidate.
90 for (auto &MI : make_range(MBB->rbegin(),
92 FromEndOfBlockToStartOfSeq.stepBackward(MI);
93 }
94
95 /// Populate InSeq with liveness information.
96 void initInSeq(const TargetRegisterInfo &TRI) {
97 assert(MBB->getParent()->getRegInfo().tracksLiveness() &&
98 "Candidate's Machine Function must track liveness");
99 // Only initialize once.
100 if (InSeqWasSet)
101 return;
102 InSeqWasSet = true;
103 InSeq.init(TRI);
104 for (auto &MI : *this)
105 InSeq.accumulate(MI);
106 }
107
108public:
109 /// The index of this \p Candidate's \p OutlinedFunction in the list of
110 /// \p OutlinedFunctions.
111 unsigned FunctionIdx = 0;
112
113 /// Identifier denoting the instructions to emit to call an outlined function
114 /// from this point. Defined by the target.
115 unsigned CallConstructionID = 0;
116
117 /// Target-specific flags for this Candidate's MBB.
118 unsigned Flags = 0x0;
119
120 /// Return the number of instructions in this Candidate.
121 unsigned getLength() const { return Len; }
122
123 /// Return the start index of this candidate.
124 unsigned getStartIdx() const { return StartIdx; }
125
126 /// Return the end index of this candidate.
127 unsigned getEndIdx() const { return StartIdx + Len - 1; }
128
129 /// Set the CallConstructionID and CallOverhead of this candidate to CID and
130 /// CO respectively.
131 void setCallInfo(unsigned CID, unsigned CO) {
132 CallConstructionID = CID;
133 CallOverhead = CO;
134 }
135
136 /// Returns the call overhead of this candidate if it is in the list.
137 unsigned getCallOverhead() const { return CallOverhead; }
138
139 MachineBasicBlock::iterator begin() { return FirstInst; }
140 MachineBasicBlock::iterator end() { return std::next(LastInst); }
141
142 MachineInstr &front() { return *FirstInst; }
143 MachineInstr &back() { return *LastInst; }
144 MachineFunction *getMF() const { return MBB->getParent(); }
145 MachineBasicBlock *getMBB() const { return MBB; }
146
147 /// \returns True if \p Reg is available from the end of the block to the
148 /// beginning of the sequence.
149 ///
150 /// This query considers the following range:
151 ///
152 /// in_seq_1
153 /// in_seq_2
154 /// ...
155 /// in_seq_n
156 /// not_in_seq_1
157 /// ...
158 /// <end of block>
160 const TargetRegisterInfo &TRI) {
161 if (!FromEndOfBlockToStartOfSeqWasSet)
162 initFromEndOfBlockToStartOfSeq(TRI);
163 return FromEndOfBlockToStartOfSeq.available(Reg);
164 }
165
166 /// \returns True if `isAvailableAcrossAndOutOfSeq` fails for any register
167 /// in \p Regs.
168 bool isAnyUnavailableAcrossOrOutOfSeq(std::initializer_list<Register> Regs,
169 const TargetRegisterInfo &TRI) {
170 if (!FromEndOfBlockToStartOfSeqWasSet)
171 initFromEndOfBlockToStartOfSeq(TRI);
172 return any_of(Regs, [&](Register Reg) {
173 return !FromEndOfBlockToStartOfSeq.available(Reg);
174 });
175 }
176
177 /// \returns True if \p Reg is available within the sequence itself.
178 ///
179 /// This query considers the following range:
180 ///
181 /// in_seq_1
182 /// in_seq_2
183 /// ...
184 /// in_seq_n
186 if (!InSeqWasSet)
187 initInSeq(TRI);
188 return InSeq.available(Reg);
189 }
190
191 /// The number of instructions that would be saved by outlining every
192 /// candidate of this type.
193 ///
194 /// This is a fixed value which is not updated during the candidate pruning
195 /// process. It is only used for deciding which candidate to keep if two
196 /// candidates overlap. The true benefit is stored in the OutlinedFunction
197 /// for some given candidate.
198 unsigned Benefit = 0;
199
200 Candidate(unsigned StartIdx, unsigned Len,
203 unsigned FunctionIdx, unsigned Flags)
204 : StartIdx(StartIdx), Len(Len), FirstInst(FirstInst), LastInst(LastInst),
206 Candidate() = delete;
207
208 /// Used to ensure that \p Candidates are outlined in an order that
209 /// preserves the start and end indices of other \p Candidates.
210 bool operator<(const Candidate &RHS) const {
211 return getStartIdx() > RHS.getStartIdx();
212 }
213
214};
215
216/// The information necessary to create an outlined function for some
217/// class of candidate.
219
220public:
221 std::vector<Candidate> Candidates;
222
223 /// The actual outlined function created.
224 /// This is initialized after we go through and create the actual function.
225 MachineFunction *MF = nullptr;
226
227 /// Represents the size of a sequence in bytes. (Some instructions vary
228 /// widely in size, so just counting the instructions isn't very useful.)
229 unsigned SequenceSize = 0;
230
231 /// Target-defined overhead of constructing a frame for this function.
232 unsigned FrameOverhead = 0;
233
234 /// Target-defined identifier for constructing a frame for this function.
236
237 /// Return the number of candidates for this \p OutlinedFunction.
238 virtual unsigned getOccurrenceCount() const { return Candidates.size(); }
239
240 /// Return the number of bytes it would take to outline this
241 /// function.
242 virtual unsigned getOutliningCost() const {
243 unsigned CallOverhead = 0;
244 for (const Candidate &C : Candidates)
245 CallOverhead += C.getCallOverhead();
246 return CallOverhead + SequenceSize + FrameOverhead;
247 }
248
249 /// Return the size in bytes of the unoutlined sequences.
250 unsigned getNotOutlinedCost() const {
252 }
253
254 /// Return the number of instructions that would be saved by outlining
255 /// this function.
256 unsigned getBenefit() const {
257 unsigned NotOutlinedCost = getNotOutlinedCost();
258 unsigned OutlinedCost = getOutliningCost();
259 return (NotOutlinedCost < OutlinedCost) ? 0
260 : NotOutlinedCost - OutlinedCost;
261 }
262
263 /// Return the number of instructions in this sequence.
264 unsigned getNumInstrs() const { return Candidates[0].getLength(); }
265
266 OutlinedFunction(std::vector<Candidate> &Candidates, unsigned SequenceSize,
267 unsigned FrameOverhead, unsigned FrameConstructionID)
270 const unsigned B = getBenefit();
271 for (Candidate &C : Candidates)
272 C.Benefit = B;
273 }
274
276 virtual ~OutlinedFunction() = default;
277};
278
279/// The information necessary to create an outlined function that is matched
280/// globally.
282 explicit GlobalOutlinedFunction(std::unique_ptr<OutlinedFunction> OF,
283 unsigned GlobalOccurrenceCount)
285
287
288 /// Return the number of times that appear globally.
289 /// Global outlining candidate is uniquely created per each match, but this
290 /// might be erased out when it's overlapped with the previous outlining
291 /// instance.
292 unsigned getOccurrenceCount() const override {
293 assert(Candidates.size() <= 1);
294 return Candidates.empty() ? 0 : GlobalOccurrenceCount;
295 }
296
297 /// Return the outlining cost using the global occurrence count
298 /// with the same cost as the first (unique) candidate.
299 unsigned getOutliningCost() const override {
300 assert(Candidates.size() <= 1);
301 unsigned CallOverhead =
302 Candidates.empty()
303 ? 0
304 : Candidates[0].getCallOverhead() * getOccurrenceCount();
305 return CallOverhead + SequenceSize + FrameOverhead;
306 }
307
310};
311
312} // namespace outliner
313} // namespace llvm
314
315#endif
MachineBasicBlock & MBB
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
IRTranslator LLVM IR MI
A set of register units.
unsigned const TargetRegisterInfo * TRI
unsigned Reg
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Value * RHS
A set of register units used to track register liveness.
Definition: LiveRegUnits.h:30
bool available(MCPhysReg Reg) const
Returns true if no part of physical register Reg is live.
Definition: LiveRegUnits.h:116
void init(const TargetRegisterInfo &TRI)
Initialize and clear the set.
Definition: LiveRegUnits.h:73
void stepBackward(const MachineInstr &MI)
Updates liveness when stepping backwards over the instruction MI.
void addLiveOuts(const MachineBasicBlock &MBB)
Adds registers living out of block MBB.
void accumulate(const MachineInstr &MI)
Adds all register units used, defined or clobbered in MI.
Representation of each machine instruction.
Definition: MachineInstr.h:69
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
InstrType
Represents how an instruction should be mapped by the outliner.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1746
An individual sequence of instructions to be replaced with a call to an outlined function.
unsigned Flags
Target-specific flags for this Candidate's MBB.
bool isAnyUnavailableAcrossOrOutOfSeq(std::initializer_list< Register > Regs, const TargetRegisterInfo &TRI)
unsigned getCallOverhead() const
Returns the call overhead of this candidate if it is in the list.
void setCallInfo(unsigned CID, unsigned CO)
Set the CallConstructionID and CallOverhead of this candidate to CID and CO respectively.
unsigned Benefit
The number of instructions that would be saved by outlining every candidate of this type.
MachineBasicBlock * getMBB() const
MachineFunction * getMF() const
MachineBasicBlock::iterator begin()
bool operator<(const Candidate &RHS) const
Used to ensure that Candidates are outlined in an order that preserves the start and end indices of o...
unsigned getEndIdx() const
Return the end index of this candidate.
Candidate(unsigned StartIdx, unsigned Len, MachineBasicBlock::iterator &FirstInst, MachineBasicBlock::iterator &LastInst, MachineBasicBlock *MBB, unsigned FunctionIdx, unsigned Flags)
unsigned CallConstructionID
Identifier denoting the instructions to emit to call an outlined function from this point.
bool isAvailableInsideSeq(Register Reg, const TargetRegisterInfo &TRI)
unsigned getStartIdx() const
Return the start index of this candidate.
MachineBasicBlock::iterator end()
bool isAvailableAcrossAndOutOfSeq(Register Reg, const TargetRegisterInfo &TRI)
unsigned getLength() const
Return the number of instructions in this Candidate.
unsigned FunctionIdx
The index of this Candidate's OutlinedFunction in the list of OutlinedFunctions.
The information necessary to create an outlined function that is matched globally.
GlobalOutlinedFunction(std::unique_ptr< OutlinedFunction > OF, unsigned GlobalOccurrenceCount)
unsigned getOccurrenceCount() const override
Return the number of times that appear globally.
unsigned getOutliningCost() const override
Return the outlining cost using the global occurrence count with the same cost as the first (unique) ...
The information necessary to create an outlined function for some class of candidate.
virtual unsigned getOccurrenceCount() const
Return the number of candidates for this OutlinedFunction.
virtual unsigned getOutliningCost() const
Return the number of bytes it would take to outline this function.
unsigned getBenefit() const
Return the number of instructions that would be saved by outlining this function.
unsigned getNotOutlinedCost() const
Return the size in bytes of the unoutlined sequences.
MachineFunction * MF
The actual outlined function created.
unsigned FrameConstructionID
Target-defined identifier for constructing a frame for this function.
unsigned getNumInstrs() const
Return the number of instructions in this sequence.
OutlinedFunction(std::vector< Candidate > &Candidates, unsigned SequenceSize, unsigned FrameOverhead, unsigned FrameConstructionID)
unsigned FrameOverhead
Target-defined overhead of constructing a frame for this function.
unsigned SequenceSize
Represents the size of a sequence in bytes.
virtual ~OutlinedFunction()=default
std::vector< Candidate > Candidates