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 /// Identifier denoting the instructions to emit to call an outlined function
112 /// from this point. Defined by the target.
113 unsigned CallConstructionID = 0;
114
115 /// Target-specific flags for this Candidate's MBB.
116 unsigned Flags = 0x0;
117
118 /// Return the number of instructions in this Candidate.
119 unsigned getLength() const { return Len; }
120
121 /// Return the start index of this candidate.
122 unsigned getStartIdx() const { return StartIdx; }
123
124 /// Return the end index of this candidate.
125 unsigned getEndIdx() const { return StartIdx + Len - 1; }
126
127 /// Set the CallConstructionID and CallOverhead of this candidate to CID and
128 /// CO respectively.
129 void setCallInfo(unsigned CID, unsigned CO) {
130 CallConstructionID = CID;
131 CallOverhead = CO;
132 }
133
134 /// Returns the call overhead of this candidate if it is in the list.
135 unsigned getCallOverhead() const { return CallOverhead; }
136
137 MachineBasicBlock::iterator begin() { return FirstInst; }
138 MachineBasicBlock::iterator end() { return std::next(LastInst); }
139
140 MachineInstr &front() { return *FirstInst; }
141 MachineInstr &back() { return *LastInst; }
142 MachineFunction *getMF() const { return MBB->getParent(); }
143 MachineBasicBlock *getMBB() const { return MBB; }
144
145 /// \returns True if \p Reg is available from the end of the block to the
146 /// beginning of the sequence.
147 ///
148 /// This query considers the following range:
149 ///
150 /// in_seq_1
151 /// in_seq_2
152 /// ...
153 /// in_seq_n
154 /// not_in_seq_1
155 /// ...
156 /// <end of block>
158 const TargetRegisterInfo &TRI) {
159 if (!FromEndOfBlockToStartOfSeqWasSet)
160 initFromEndOfBlockToStartOfSeq(TRI);
161 return FromEndOfBlockToStartOfSeq.available(Reg);
162 }
163
164 /// \returns True if `isAvailableAcrossAndOutOfSeq` fails for any register
165 /// in \p Regs.
166 bool isAnyUnavailableAcrossOrOutOfSeq(std::initializer_list<Register> Regs,
167 const TargetRegisterInfo &TRI) {
168 if (!FromEndOfBlockToStartOfSeqWasSet)
169 initFromEndOfBlockToStartOfSeq(TRI);
170 return any_of(Regs, [&](Register Reg) {
171 return !FromEndOfBlockToStartOfSeq.available(Reg);
172 });
173 }
174
175 /// \returns True if \p Reg is available within the sequence itself.
176 ///
177 /// This query considers the following range:
178 ///
179 /// in_seq_1
180 /// in_seq_2
181 /// ...
182 /// in_seq_n
184 if (!InSeqWasSet)
185 initInSeq(TRI);
186 return InSeq.available(Reg);
187 }
188
189 /// The number of instructions that would be saved by outlining every
190 /// candidate of this type.
191 ///
192 /// This is a fixed value which is not updated during the candidate pruning
193 /// process. It is only used for deciding which candidate to keep if two
194 /// candidates overlap. The true benefit is stored in the OutlinedFunction
195 /// for some given candidate.
196 unsigned Benefit = 0;
197
198 Candidate(unsigned StartIdx, unsigned Len,
201 unsigned Flags)
202 : StartIdx(StartIdx), Len(Len), FirstInst(FirstInst), LastInst(LastInst),
203 MBB(MBB), Flags(Flags) {}
204 Candidate() = delete;
205
206 /// Used to ensure that \p Candidates are outlined in an order that
207 /// preserves the start and end indices of other \p Candidates.
208 bool operator<(const Candidate &RHS) const {
209 return getStartIdx() > RHS.getStartIdx();
210 }
211
212};
213
214/// The information necessary to create an outlined function for some
215/// class of candidate.
217
218public:
219 std::vector<Candidate> Candidates;
220
221 /// The actual outlined function created.
222 /// This is initialized after we go through and create the actual function.
223 MachineFunction *MF = nullptr;
224
225 /// Represents the size of a sequence in bytes. (Some instructions vary
226 /// widely in size, so just counting the instructions isn't very useful.)
227 unsigned SequenceSize = 0;
228
229 /// Target-defined overhead of constructing a frame for this function.
230 unsigned FrameOverhead = 0;
231
232 /// Target-defined identifier for constructing a frame for this function.
234
235 /// Return the number of candidates for this \p OutlinedFunction.
236 virtual unsigned getOccurrenceCount() const { return Candidates.size(); }
237
238 /// Return the number of bytes it would take to outline this
239 /// function.
240 virtual unsigned getOutliningCost() const {
241 unsigned CallOverhead = 0;
242 for (const Candidate &C : Candidates)
243 CallOverhead += C.getCallOverhead();
244 return CallOverhead + SequenceSize + FrameOverhead;
245 }
246
247 /// Return the size in bytes of the unoutlined sequences.
248 unsigned getNotOutlinedCost() const {
250 }
251
252 /// Return the number of instructions that would be saved by outlining
253 /// this function.
254 unsigned getBenefit() const {
255 unsigned NotOutlinedCost = getNotOutlinedCost();
256 unsigned OutlinedCost = getOutliningCost();
257 return (NotOutlinedCost < OutlinedCost) ? 0
258 : NotOutlinedCost - OutlinedCost;
259 }
260
261 /// Return the number of instructions in this sequence.
262 unsigned getNumInstrs() const { return Candidates[0].getLength(); }
263
264 OutlinedFunction(std::vector<Candidate> &Candidates, unsigned SequenceSize,
265 unsigned FrameOverhead, unsigned FrameConstructionID)
268 const unsigned B = getBenefit();
269 for (Candidate &C : Candidates)
270 C.Benefit = B;
271 }
272
274 virtual ~OutlinedFunction() = default;
275};
276
277/// The information necessary to create an outlined function that is matched
278/// globally.
280 explicit GlobalOutlinedFunction(std::unique_ptr<OutlinedFunction> OF,
281 unsigned GlobalOccurrenceCount)
283
285
286 /// Return the number of times that appear globally.
287 /// Global outlining candidate is uniquely created per each match, but this
288 /// might be erased out when it's overlapped with the previous outlining
289 /// instance.
290 unsigned getOccurrenceCount() const override {
291 assert(Candidates.size() <= 1);
292 return Candidates.empty() ? 0 : GlobalOccurrenceCount;
293 }
294
295 /// Return the outlining cost using the global occurrence count
296 /// with the same cost as the first (unique) candidate.
297 unsigned getOutliningCost() const override {
298 assert(Candidates.size() <= 1);
299 unsigned CallOverhead =
300 Candidates.empty()
301 ? 0
302 : Candidates[0].getCallOverhead() * getOccurrenceCount();
303 return CallOverhead + SequenceSize + FrameOverhead;
304 }
305
307 ~GlobalOutlinedFunction() override = default;
308};
309
310} // namespace outliner
311} // namespace llvm
312
313#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:1762
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.
unsigned CallConstructionID
Identifier denoting the instructions to emit to call an outlined function from this point.
Candidate(unsigned StartIdx, unsigned Len, MachineBasicBlock::iterator &FirstInst, MachineBasicBlock::iterator &LastInst, MachineBasicBlock *MBB, unsigned Flags)
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.
~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