LLVM 24.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 if (!MI.isDebugInstr())
93 FromEndOfBlockToStartOfSeq.stepBackward(MI);
94 }
95
96 /// Populate InSeq with liveness information.
97 void initInSeq(const TargetRegisterInfo &TRI) {
98 assert(MBB->getParent()->getRegInfo().tracksLiveness() &&
99 "Candidate's Machine Function must track liveness");
100 // Only initialize once.
101 if (InSeqWasSet)
102 return;
103 InSeqWasSet = true;
104 InSeq.init(TRI);
105 for (auto &MI : *this)
106 if (!MI.isDebugInstr())
107 InSeq.accumulate(MI);
108 }
109
110public:
111 /// The index of this \p Candidate's \p OutlinedFunction in the list of
112 /// \p OutlinedFunctions.
113 unsigned FunctionIdx = 0;
114
115 /// Identifier denoting the instructions to emit to call an outlined function
116 /// from this point. Defined by the target.
117 unsigned CallConstructionID = 0;
118
119 /// Target-specific flags for this Candidate's MBB.
120 unsigned Flags = 0x0;
121
122 /// Return the number of instructions in this Candidate.
123 unsigned getLength() const { return Len; }
124
125 /// Return the start index of this candidate.
126 unsigned getStartIdx() const { return StartIdx; }
127
128 /// Return the end index of this candidate.
129 unsigned getEndIdx() const { return StartIdx + Len - 1; }
130
131 /// Set the CallConstructionID and CallOverhead of this candidate to CID and
132 /// CO respectively.
133 void setCallInfo(unsigned CID, unsigned CO) {
134 CallConstructionID = CID;
135 CallOverhead = CO;
136 }
137
138 /// Returns the call overhead of this candidate if it is in the list.
139 unsigned getCallOverhead() const { return CallOverhead; }
140
141 MachineBasicBlock::iterator begin() { return FirstInst; }
142 MachineBasicBlock::iterator end() { return std::next(LastInst); }
143
144 MachineInstr &front() { return *FirstInst; }
145 MachineInstr &back() { return *LastInst; }
146 MachineFunction *getMF() const { return MBB->getParent(); }
147 MachineBasicBlock *getMBB() const { return MBB; }
148
149 /// \returns True if \p Reg is available from the end of the block to the
150 /// beginning of the sequence.
151 ///
152 /// This query considers the following range:
153 ///
154 /// in_seq_1
155 /// in_seq_2
156 /// ...
157 /// in_seq_n
158 /// not_in_seq_1
159 /// ...
160 /// <end of block>
162 const TargetRegisterInfo &TRI) {
163 if (!FromEndOfBlockToStartOfSeqWasSet)
164 initFromEndOfBlockToStartOfSeq(TRI);
165 return FromEndOfBlockToStartOfSeq.available(Reg);
166 }
167
168 /// \returns True if `isAvailableAcrossAndOutOfSeq` fails for any register
169 /// in \p Regs.
170 bool isAnyUnavailableAcrossOrOutOfSeq(std::initializer_list<Register> Regs,
171 const TargetRegisterInfo &TRI) {
172 if (!FromEndOfBlockToStartOfSeqWasSet)
173 initFromEndOfBlockToStartOfSeq(TRI);
174 return any_of(Regs, [&](Register Reg) {
175 return !FromEndOfBlockToStartOfSeq.available(Reg);
176 });
177 }
178
179 /// \returns True if \p Reg is available within the sequence itself.
180 ///
181 /// This query considers the following range:
182 ///
183 /// in_seq_1
184 /// in_seq_2
185 /// ...
186 /// in_seq_n
188 if (!InSeqWasSet)
189 initInSeq(TRI);
190 return InSeq.available(Reg);
191 }
192
193 /// The number of instructions that would be saved by outlining every
194 /// candidate of this type.
195 ///
196 /// This is a fixed value which is not updated during the candidate pruning
197 /// process. It is only used for deciding which candidate to keep if two
198 /// candidates overlap. The true benefit is stored in the OutlinedFunction
199 /// for some given candidate.
200 unsigned Benefit = 0;
201
202 Candidate(unsigned StartIdx, unsigned Len,
205 unsigned FunctionIdx, unsigned Flags)
206 : StartIdx(StartIdx), Len(Len), FirstInst(FirstInst), LastInst(LastInst),
207 MBB(MBB), FunctionIdx(FunctionIdx), Flags(Flags) {}
208 Candidate() = delete;
209
210 /// Used to ensure that \p Candidates are outlined in an order that
211 /// preserves the start and end indices of other \p Candidates.
212 bool operator<(const Candidate &RHS) const {
213 return getStartIdx() > RHS.getStartIdx();
214 }
215
216};
217
218/// The information necessary to create an outlined function for some
219/// class of candidate.
221
222public:
223 std::vector<Candidate> Candidates;
224
225 /// The actual outlined function created.
226 /// This is initialized after we go through and create the actual function.
227 MachineFunction *MF = nullptr;
228
229 /// Represents the size of a sequence in bytes. (Some instructions vary
230 /// widely in size, so just counting the instructions isn't very useful.)
231 unsigned SequenceSize = 0;
232
233 /// Target-defined overhead of constructing a frame for this function.
234 unsigned FrameOverhead = 0;
235
236 /// Target-defined identifier for constructing a frame for this function.
238
239 /// Return the number of candidates for this \p OutlinedFunction.
240 virtual unsigned getOccurrenceCount() const { return Candidates.size(); }
241
242 /// Return the number of bytes it would take to outline this
243 /// function.
244 virtual unsigned getOutliningCost() const {
245 unsigned CallOverhead = 0;
246 for (const Candidate &C : Candidates)
247 CallOverhead += C.getCallOverhead();
248 return CallOverhead + SequenceSize + FrameOverhead;
249 }
250
251 /// Return the size in bytes of the unoutlined sequences.
252 unsigned getNotOutlinedCost() const {
254 }
255
256 /// Return the number of instructions that would be saved by outlining
257 /// this function.
258 unsigned getBenefit() const {
259 unsigned NotOutlinedCost = getNotOutlinedCost();
260 unsigned OutlinedCost = getOutliningCost();
261 return (NotOutlinedCost < OutlinedCost) ? 0
262 : NotOutlinedCost - OutlinedCost;
263 }
264
265 /// Return the number of instructions in this sequence.
266 unsigned getNumInstrs() const { return Candidates[0].getLength(); }
267
268 OutlinedFunction(std::vector<Candidate> &Candidates, unsigned SequenceSize,
269 unsigned FrameOverhead, unsigned FrameConstructionID)
272 const unsigned B = getBenefit();
273 for (Candidate &C : Candidates)
274 C.Benefit = B;
275 }
276
278 virtual ~OutlinedFunction() = default;
279};
280
281/// The information necessary to create an outlined function that is matched
282/// globally.
284 explicit GlobalOutlinedFunction(std::unique_ptr<OutlinedFunction> OF,
285 unsigned GlobalOccurrenceCount)
287
289
290 /// Return the number of times that appear globally.
291 /// Global outlining candidate is uniquely created per each match, but this
292 /// might be erased out when it's overlapped with the previous outlining
293 /// instance.
294 unsigned getOccurrenceCount() const override {
295 assert(Candidates.size() <= 1);
296 return Candidates.empty() ? 0 : GlobalOccurrenceCount;
297 }
298
299 /// Return the outlining cost using the global occurrence count
300 /// with the same cost as the first (unique) candidate.
301 unsigned getOutliningCost() const override {
302 assert(Candidates.size() <= 1);
303 unsigned CallOverhead =
304 Candidates.empty()
305 ? 0
306 : Candidates[0].getCallOverhead() * getOccurrenceCount();
307 return CallOverhead + SequenceSize + FrameOverhead;
308 }
309
311 ~GlobalOutlinedFunction() override = default;
312};
313
314} // namespace outliner
315} // namespace llvm
316
317#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
IRTranslator LLVM IR MI
A set of register units.
Register Reg
Register const TargetRegisterInfo * TRI
Value * RHS
A set of register units used to track register liveness.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
MachineInstrBundleIterator< MachineInstr > iterator
Representation of each machine instruction.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
InstrType
Represents how an instruction should be mapped by the outliner.
This is an optimization pass for GlobalISel generic memory operations.
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.
~GlobalOutlinedFunction() override=default
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) ...
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