LLVM 23.0.0git
Rematerializer.h
Go to the documentation of this file.
1//=====-- Rematerializer.h - MIR rematerialization support ------*- 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/// MIR-level target-independent rematerialization helpers.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CODEGEN_REMATERIALIZER_H
15#define LLVM_CODEGEN_REMATERIALIZER_H
16
17#include "llvm/ADT/STLExtras.h"
24#include <iterator>
25
26namespace llvm {
27
28/// MIR-level target-independent rematerializer. Provides an API to identify and
29/// rematerialize registers within a machine function.
30///
31/// At the moment this supports rematerializing registers that meet all of the
32/// following constraints.
33/// 1. The register is virtual and has a single defining instruction.
34/// 2. The single defining instruction is deemed rematerializable by the TII and
35/// doesn't have any physical register use that is both non-constant and
36/// non-ignorable.
37/// 3. The register has at least one non-debug use that is inside or at a region
38/// boundary (see below for what we consider to be a region).
39///
40/// Rematerializable registers (represented by \ref Rematerializer::Reg) form a
41/// DAG of their own, with every register having incoming edges from all
42/// rematerializable registers which are read by the instruction defining it. It
43/// is possible to rematerialize registers with unrematerializable dependencies;
44/// however the latter are not considered part of this DAG since their
45/// position/identity never change and therefore do not require the same level
46/// of tracking.
47///
48/// Each register has a "dependency DAG" which is defined as the subset of nodes
49/// in the overall DAG that have at least one path to the register, which is
50/// called the "root" register in this context. Semantically, these nodes are
51/// the registers which are involved into the computation of the root register
52/// i.e., all of its transitive dependencies. We use the term "root" because all
53/// paths within the dependency DAG of a register terminate at it; however,
54/// there may be multiple paths between a non-root node and the root node, so a
55/// dependency DAG is not always a tree.
56///
57/// The API uses dense unsigned integers starting at 0 to reference
58/// rematerializable registers. These indices are immutable i.e., even when
59/// registers are deleted their respective integer handle remain valid. Method
60/// which perform actual rematerializations should however be assumed to
61/// invalidate addresses to \ref Rematerializer::Reg objects.
62///
63/// The rematerializer tracks def/use points of registers based on regions.
64/// These are alike the regions the machine scheduler works on. A region is
65/// simply a pair on MBB iterators encoding a range of machine instructions. The
66/// first iterator (beginning of the region) is inclusive whereas the second
67/// iterator (end of the region) is exclusive and can either point to a MBB's
68/// end sentinel or an actual MI (not necessarily a terminator). Regions must be
69/// non-empty, cannot overlap, and cannot contain terminators. However, they do
70/// not have to cover the whole function.
71///
72/// The API uses dense unsigned integers starting at 0 to reference regions.
73/// These map directly to the indices of the corresponding regions in the region
74/// vector passed during construction.
75///
76/// The rematerializer supports rematerializing arbitrary complex DAGs of
77/// registers to regions where these registers are used, with the option of
78/// re-using non-root registers or their previous rematerializations instead of
79/// rematerializing them again. It also optionally supports rolling back
80/// previous rematerializations (set during analysis phase, see \ref
81/// Rematerializer::analyze) to restore the MIR state to what it was
82/// pre-rematerialization. When enabled, machine instructions defining
83/// rematerializable registers that no longer have any uses following previous
84/// rematerializations will not be deleted from the MIR; their opcode will
85/// instead be set to a DEBUG_VALUE and their read register operands set to the
86/// null register. This maintains their position in the MIR and keeps the
87/// original register alive for potential rollback while allowing other
88/// passes/analyzes (e.g., machine scheduler, live-interval analysis) to ignore
89/// them. \ref Rematerializer::commitRematerializations actually deletes those
90/// instructions when rollback is deemed unnecessary.
91///
92/// Throughout its lifetime, the rematerializer tracks new registers it creates
93/// (which are rematerializable by construction) and their relations to other
94/// registers. It performs DAG updates immediately on rematerialization but
95/// defers/batches all necessary live interval updates to reduce the number of
96/// expensive LIS queries when successively rematerializing many registers. \ref
97/// Rematerializer::updateLiveIntervals performs all currently batched live
98/// interval updates.
99///
100/// In its nomenclature, the rematerializer differentiates between "original
101/// registers" (registers that were present when it analyzed the function) and
102/// rematerializations of these original registers. Rematerializations have an
103/// "origin" which is the index of the original regiser they were rematerialized
104/// from (transitivity applies; a rematerialization and all of its own
105/// rematerializations have the same origin). Semantically, only original
106/// registers have rematerializations.
108public:
109 /// Index type for rematerializable registers.
111
112 /// A rematerializable register defined by a single machine instruction.
113 ///
114 /// A rematerializable register has a set of dependencies, which correspond
115 /// to the unique read register operands of its defining instruction.
116 /// They are identified by their machine operand index, and can themselves be
117 /// rematerializable. Operand indices corresponding to unrematerializable
118 /// dependencies are managed by and queried from the rematerializer.
119 ///
120 /// A rematerializable register also has an arbitrary number of users in an
121 /// arbitrary number of regions, potentially including its own defining
122 /// region. When rematerializations lead to operand changes in users, a
123 /// register may find itself without any user left, at which point the
124 /// rematerializer marks it for deletion. Its defining instruction either
125 /// becomes nullptr (without rollback support) or its opcode is set to
126 /// TargetOpcode::DBG_VALUE (with rollback support) until \ref
127 /// Rematerializer::commitRematerializations is called.
128 struct Reg {
129 /// Single MI defining the rematerializable register.
131 /// Defining region of \p DefMI.
132 unsigned DefRegion;
133 /// The rematerializable register's lane bitmask.
135
137 /// Uses of the register, mapped by region.
139
140 /// A read register operand of \p DefMI that is rematerializable (according
141 /// to the rematerializer).
142 struct Dependency {
143 /// The register's machine operand index in \p DefMI.
144 unsigned MOIdx;
145 /// The corresponding register's index in the rematerializer.
147
150 };
151 /// This register's rematerializable dependencies, one per unique
152 /// rematerializable register operand.
154
155 /// Returns the rematerializable register from its defining instruction.
156 inline Register getDefReg() const {
157 assert(DefMI && "defining instruction was deleted");
158 assert(DefMI->getOperand(0).isDef() && "not a register def");
159 return DefMI->getOperand(0).getReg();
160 }
161
162 bool hasUsersInDefRegion() const {
163 return !Uses.empty() && Uses.contains(DefRegion);
164 }
165
167 if (Uses.empty())
168 return false;
169 return Uses.size() > 1 || Uses.begin()->first != DefRegion;
170 }
171
172 /// Returns the first and last user of the register in region \p UseRegion.
173 /// If the register has no user in the region, returns a pair of nullptr's.
174 std::pair<MachineInstr *, MachineInstr *>
175 getRegionUseBounds(unsigned UseRegion, const LiveIntervals &LIS) const;
176
177 bool isAlive() const {
178 return DefMI && DefMI->getOpcode() != TargetOpcode::DBG_VALUE;
179 }
180
181 private:
182 void addUser(MachineInstr *MI, unsigned Region);
183 void addUsers(const RegionUsers &NewUsers, unsigned Region);
184 void eraseUser(MachineInstr *MI, unsigned Region);
185
186 friend Rematerializer;
187 };
188
189 /// Rematerializer listener. Defines overridable hooks that allow to catch
190 /// specific events inside the rematerializer. All hooks do nothing by
191 /// default. Listeners can be added or removed at any time during the
192 /// rematerializer's lifetime.
193 class Listener {
194 public:
196
197 /// Called just after register \p NewRegIdx is created (following a
198 /// rematerialization). At this point the rematerialization exists in the \p
199 /// Remater state and the MIR but does not yet have any user.
200 virtual void rematerializerNoteRegCreated(const Rematerializer &Remater,
201 RegisterIdx NewRegIdx) {}
202
203 /// Called juste before register \p RegIdx is deleted from the MIR. At this
204 /// point the register still exists in the MIR but no longer has any user.
205 virtual void rematerializerNoteRegDeleted(const Rematerializer &Remater,
206 RegisterIdx RegIdx) {}
207
208 virtual ~Listener() = default;
209
210 private:
211 virtual void anchor();
212 };
213
214 /// Error value for register indices.
215 static constexpr unsigned NoReg = ~0;
216
217 /// A region's boundaries i.e. a pair of instruction bundle iterators. The
218 /// lower boundary is inclusive, the upper boundary is exclusive.
220 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>;
221
222 /// Simply initializes some internal state, does not identify
223 /// rematerialization candidates.
226 LiveIntervals &LIS);
227
228 /// Goes through the whole MF and identifies all rematerializable registers.
229 /// When \p SupportRollback is set, rematerializations of original registers
230 /// can be rolled back and original registers are maintained in the IR even
231 /// when they longer have any users. Returns whether there is any
232 /// rematerializable register in regions.
233 bool analyze(bool SupportRollback);
234
235 /// Adds a new listener to the rematerializer.
236 void addListener(Listener *Listen) {
237 assert(Listen && "null listener");
238 assert(!Listeners.contains(Listen) && "duplicate listener");
239 Listeners.insert(Listen);
240 }
241
242 /// Removes a listener from the rematerializer.
243 void removeListener(Listener *Listen) {
244 assert(Listeners.contains(Listen) && "unknown listener");
245 Listeners.erase(Listen);
246 }
247
248 /// Removes all listeners from the rematerializer.
249 void clearListeners() { Listeners.clear(); }
250
251 inline const Reg &getReg(RegisterIdx RegIdx) const {
252 assert(RegIdx < Regs.size() && "out of bounds");
253 return Regs[RegIdx];
254 };
255 inline ArrayRef<Reg> getRegs() const { return Regs; };
256 inline unsigned getNumRegs() const { return Regs.size(); };
257
258 inline const RegionBoundaries &getRegion(RegisterIdx RegionIdx) {
259 assert(RegionIdx < Regions.size() && "out of bounds");
260 return Regions[RegionIdx];
261 }
262 inline unsigned getNumRegions() const { return Regions.size(); }
263
264 /// Whether register \p RegIdx is a rematerialization of some original
265 /// register.
266 inline bool isRematerializedRegister(RegisterIdx RegIdx) const {
267 assert(RegIdx < Regs.size() && "out of bounds");
268 return RegIdx >= UnrematableOprds.size();
269 }
270 /// Returns the origin index of rematerializable register \p RegIdx.
271 inline RegisterIdx getOriginOf(RegisterIdx RematRegIdx) const {
272 assert(isRematerializedRegister(RematRegIdx) && "not a rematerialization");
273 return Origins[RematRegIdx - UnrematableOprds.size()];
274 }
275 /// If \p RegIdx is a rematerialization, returns its origin's index. If it is
276 /// an original register's index, returns the same index.
278 if (isRematerializedRegister(RegIdx))
279 return getOriginOf(RegIdx);
280 return RegIdx;
281 }
282 /// Returns operand indices corresponding to unrematerializable operands for
283 /// any register \p RegIdx.
284 inline ArrayRef<unsigned> getUnrematableOprds(unsigned RegIdx) const {
285 return UnrematableOprds[getOriginOrSelf(RegIdx)];
286 }
287
288 /// When rematerializating a register (called the "root" register in this
289 /// context) to a given position, we must decide what to do with all its
290 /// rematerializable dependencies (for unrematerializable dependencies, we
291 /// have no choice but to re-use the same register). For each rematerializable
292 /// dependency we can either
293 /// 1. rematerialize it along with the register,
294 /// 2. re-use it as-is, or
295 /// 3. re-use a pre-existing rematerialization of it.
296 /// In case 1, the same decision needs to be made for all of the dependency's
297 /// dependencies. In cases 2 and 3, the dependency's dependencies need not be
298 /// examined.
299 ///
300 /// This struct allows to encode decisions of types (2) and (3) when
301 /// rematerialization of all of the root's dependency DAG is undesirable.
302 /// During rematerialization, registers in the root's dependency DAG which
303 /// have a path to the root made up exclusively of non-re-used registers will
304 /// be rematerialized along with the root.
306 /// Keys and values are rematerializable register indices.
307 ///
308 /// Before rematerialization, this only contains entries for non-root
309 /// registers of the root's dependency DAG which should not be
310 /// rematerialized i.e., for which an existing register should be used
311 /// instead. These map each such non-root register to either the same
312 /// register (case 2, \ref DependencyReuseInfo::reuse) or to a
313 /// rematerialization of the key register (case 3, \ref
314 /// DependencyReuseInfo::useRemat).
315 ///
316 /// After rematerialization, this contains additional entries for non-root
317 /// registers of the root's dependency DAG that needed to be rematerialized
318 /// along the root. These map each such non-root register to their
319 /// corresponding new rematerialization that is used in the rematerialized
320 /// root's dependency DAG. It follows that the difference in map size before
321 /// and after rematerialization indicates the number of non-root registers
322 /// that were rematerialized along the root.
324
326 DependencyMap.insert({DepIdx, DepIdx});
327 return *this;
328 }
330 DependencyMap.insert({DepIdx, DepRematIdx});
331 return *this;
332 }
334 DependencyMap.clear();
335 return *this;
336 }
337 };
338
339 /// Rematerializes register \p RootIdx just before its first user inside
340 /// region \p UseRegion (or at the end of the region if it has no user),
341 /// transfers all its users in the region to the new register, and returns the
342 /// latter's index. The root's dependency DAG is rematerialized or re-used
343 /// according to \p DRI.
344 ///
345 /// When the method returns, \p DRI contains additional entries for non-root
346 /// registers of the root's dependency DAG that needed to be rematerialized
347 /// along the root. References to \ref Rematerializer::Reg should be
348 /// considered invalidated by calls to this method.
349 RegisterIdx rematerializeToRegion(RegisterIdx RootIdx, unsigned UseRegion,
350 DependencyReuseInfo &DRI);
351
352 /// Rematerializes register \p RootIdx before position \p InsertPos in \p
353 /// UseRegion and returns the new register's index. The root's dependency DAG
354 /// is rematerialized or re-used according to \p DRI.
355 ///
356 /// When the method returns, \p DRI contains additional entries for non-root
357 /// registers of the root's dependency DAG that needed to be rematerialized
358 /// along the root. References to \ref Rematerializer::Reg should be
359 /// considered invalidated by calls to this method.
360 RegisterIdx rematerializeToPos(RegisterIdx RootIdx, unsigned UseRegion,
362 DependencyReuseInfo &DRI);
363
364 /// Rolls back all rematerializations of original register \p RootIdx,
365 /// transfering all their users back to it and permanently deleting them from
366 /// the MIR. The root register is revived if it was fully rematerialized (this
367 /// requires that rollback support was set at that time). Transitive
368 /// dependencies of the root register that were fully rematerialized are
369 /// re-vived at their original positions; this requires that rollback support
370 /// was set when they were rematerialized.
371 void rollbackRematsOf(RegisterIdx RootIdx);
372
373 /// Rolls back register \p RematIdx (which must be a rematerialization)
374 /// transfering all its users back to its origin. The latter is revived if it
375 /// was fully rematerialized (this requires that rollback support was set at
376 /// that time).
377 void rollback(RegisterIdx RematIdx);
378
379 /// Revives original register \p RootIdx at its original position in the MIR
380 /// if it was fully rematerialized with rollback support set. Transitive
381 /// dependencies of the root register that were fully rematerialized are
382 /// revived at their original positions; this requires that rollback support
383 /// was set when they were themselves rematerialized.
384 void reviveRegIfDead(RegisterIdx RootIdx);
385
386 /// Transfers all users of register \p FromRegIdx in region \p UseRegion to \p
387 /// ToRegIdx, the latter of which must be a rematerialization of the former or
388 /// have the same origin register. Users in \p UseRegion must be reachable
389 /// from \p ToRegIdx.
390 void transferRegionUsers(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx,
391 unsigned UseRegion);
392
393 /// Transfers user \p UserMI in region \p UserRegion from register \p
394 /// FromRegIdx to \p ToRegIdx, the latter of which must be a rematerialization
395 /// of the former or have the same origin register. \p UserMI must be a direct
396 /// user of \p FromRegIdx. \p UserMI must be reachable from \p ToRegIdx.
397 void transferUser(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx,
398 unsigned UserRegion, MachineInstr &UserMI);
399
400 /// Recomputes all live intervals that have changed as a result of previous
401 /// rematerializations/rollbacks.
402 void updateLiveIntervals();
403
404 /// Deletes unused rematerialized registers that were left in the MIR to
405 /// support rollback.
407
408 /// Determines whether (sub-)register operand \p MO has the same value at
409 /// all \p Uses as at \p MO. This implies that it is also available at all \p
410 /// Uses according to its current live interval.
412
413 /// Finds the closest rematerialization of register \p RegIdx in region \p
414 /// Region that exists before slot \p Before. If no such rematerialization
415 /// exists, returns \ref Rematerializer::NoReg.
417 SlotIndex Before) const;
418
420 Printable printID(RegisterIdx RegIdx) const;
421 Printable printRematReg(RegisterIdx RegIdx, bool SkipRegions = false) const;
422 Printable printRegUsers(RegisterIdx RegIdx) const;
424 std::optional<unsigned> UseRegion = std::nullopt) const;
425
426private:
429 LiveIntervals &LIS;
430 const TargetInstrInfo &TII;
431 const TargetRegisterInfo &TRI;
433
434 void noteRegCreated(RegisterIdx RegIdx) const {
435 for (Listener *Listen : Listeners)
436 Listen->rematerializerNoteRegCreated(*this, RegIdx);
437 }
438
439 void noteRegDeleted(RegisterIdx RegIdx) const {
440 for (Listener *Listen : Listeners)
441 Listen->rematerializerNoteRegDeleted(*this, RegIdx);
442 }
443
444 /// Rematerializable registers identified since the rematerializer's creation,
445 /// both dead and alive, originals and rematerializations. No register is ever
446 /// deleted. Indices inside this vector serve as handles for rematerializable
447 /// registers.
448 SmallVector<Reg> Regs;
449 /// For each original register, stores indices of its read register operands
450 /// which are unrematerializable. This doesn't change after the initial
451 /// collection period, so the size of the vector indicates the number of
452 /// original registers.
453 SmallVector<SmallVector<unsigned, 2>> UnrematableOprds;
454 /// Indicates the original register index of each rematerialization, in the
455 /// order in which they are created. The size of the vector indicates the
456 /// total number of rematerializations ever created, including those that were
457 /// deleted or rolled back.
459 using RematsOf = SmallDenseSet<RegisterIdx, 4>;
460 /// Maps original register indices to their currently alive
461 /// rematerializations. In practice most registers don't have
462 /// rematerializations so this is represented as a map to lower memory cost.
463 DenseMap<RegisterIdx, RematsOf> Rematerializations;
464
465 /// Registers mapped to the index of their corresponding rematerialization
466 /// data in the \ref Regs vector. This includes registers that no longer exist
467 /// in the MIR.
468 DenseMap<Register, RegisterIdx> RegToIdx;
469 /// Parent block of each region, in order.
471 /// Set of registers whose live-range may have changed during past
472 /// rematerializations/rollbacks.
473 DenseSet<RegisterIdx> LISUpdates;
474 /// Keys are fully rematerialized registers whose rematerializations are
475 /// currently rollback-able. Values map register machine operand indices to
476 /// their original register.
477 DenseMap<RegisterIdx, DenseMap<unsigned, Register>> Revivable;
478 /// Whether all rematerializations of registers identified during the last
479 /// analysis phase will be rollback-able.
480 bool SupportRollback = false;
481
482 /// During the analysis phase, creates a \ref Rematerializer::Reg object for
483 /// virtual register \p VirtRegIdx if it is rematerializable. \p MIRegion maps
484 /// all MIs to their parent region. Set bits in \p SeenRegs indicate virtual
485 /// register indices that have already been visited.
486 void
487 addRegIfRematerializable(unsigned VirtRegIdx,
488 const DenseMap<MachineInstr *, unsigned> &MIRegion,
489 BitVector &SeenRegs);
490
491 /// Determines whether \p MI is considered rematerializable. This further
492 /// restricts constraints imposed by the TII on rematerializable instructions,
493 /// requiring for example that the defined register is virtual and only
494 /// defined once.
495 bool isMIRematerializable(const MachineInstr &MI) const;
496
497 /// Rematerializes register \p RegIdx at \p InsertPos in \p UseRegion, adding
498 /// the new rematerializable register to the backing vector \ref Regs and
499 /// returning its index inside the vector. Sets the new registers'
500 /// rematerializable dependencies to \p Dependencies (these are assumed to
501 /// already exist in the MIR) and its unrematerializable dependencies to the
502 /// same as \p RegIdx. The new register initially has no user. Since the
503 /// method appends to \ref Regs, references to elements within it should be
504 /// considered invalidated across calls to this method unless the vector can
505 /// be guaranteed to have enough space for an extra element.
506 RegisterIdx rematerializeReg(RegisterIdx RegIdx, unsigned UseRegion,
508 SmallVectorImpl<Reg::Dependency> &&Dependencies);
509
510 /// Implementation of \ref Rematerializer::transferUser that doesn't update
511 /// register users.
512 void transferUserImpl(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx,
513 MachineInstr &UserMI);
514
515 /// Deletes register \p RootIdx if it no longer has any user. If the register
516 /// is deleted, recursively deletes any of its transitive rematerializable
517 /// dependencies that no longer have users as a result.
518 void deleteRegIfUnused(RegisterIdx RootIdx);
519
520 /// Deletes rematerializable register \p RegIdx from the DAG and relevant
521 /// internal state.
522 void deleteReg(RegisterIdx RegIdx);
523
524 /// If \p MI's first operand defines a register and that register is a
525 /// rematerializable register tracked by the rematerializer, returns its
526 /// index in the \ref Regs vector. Otherwise returns \ref
527 /// Rematerializer::NoReg.
528 RegisterIdx getDefRegIdx(const MachineInstr &MI) const;
529};
530
531} // namespace llvm
532
533#endif // LLVM_CODEGEN_REMATERIALIZER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Register const TargetRegisterInfo * TRI
Rematerializer::RegisterIdx RegisterIdx
Remove Loads Into Fake Uses
This file contains some templates that are useful if you are working with the STL at all.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
MachineInstrBundleIterator< MachineInstr > iterator
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Simple wrapper around std::function<void(raw_ostream&)>.
Definition Printable.h:38
Wrapper class representing virtual and physical registers.
Definition Register.h:20
Rematerializer listener.
virtual void rematerializerNoteRegCreated(const Rematerializer &Remater, RegisterIdx NewRegIdx)
Called just after register NewRegIdx is created (following a rematerialization).
virtual void rematerializerNoteRegDeleted(const Rematerializer &Remater, RegisterIdx RegIdx)
Called juste before register RegIdx is deleted from the MIR.
Rematerializer::RegisterIdx RegisterIdx
Printable printDependencyDAG(RegisterIdx RootIdx) const
void clearListeners()
Removes all listeners from the rematerializer.
RegisterIdx getOriginOrSelf(RegisterIdx RegIdx) const
If RegIdx is a rematerialization, returns its origin's index.
static constexpr unsigned NoReg
Error value for register indices.
Printable printID(RegisterIdx RegIdx) const
ArrayRef< Reg > getRegs() const
RegisterIdx rematerializeToPos(RegisterIdx RootIdx, unsigned UseRegion, MachineBasicBlock::iterator InsertPos, DependencyReuseInfo &DRI)
Rematerializes register RootIdx before position InsertPos in UseRegion and returns the new register's...
void rollbackRematsOf(RegisterIdx RootIdx)
Rolls back all rematerializations of original register RootIdx, transfering all their users back to i...
unsigned getNumRegs() const
RegisterIdx getOriginOf(RegisterIdx RematRegIdx) const
Returns the origin index of rematerializable register RegIdx.
const Reg & getReg(RegisterIdx RegIdx) const
void updateLiveIntervals()
Recomputes all live intervals that have changed as a result of previous rematerializations/rollbacks.
RegisterIdx rematerializeToRegion(RegisterIdx RootIdx, unsigned UseRegion, DependencyReuseInfo &DRI)
Rematerializes register RootIdx just before its first user inside region UseRegion (or at the end of ...
std::pair< MachineBasicBlock::iterator, MachineBasicBlock::iterator > RegionBoundaries
A region's boundaries i.e.
bool analyze(bool SupportRollback)
Goes through the whole MF and identifies all rematerializable registers.
void rollback(RegisterIdx RematIdx)
Rolls back register RematIdx (which must be a rematerialization) transfering all its users back to it...
unsigned RegisterIdx
Index type for rematerializable registers.
void reviveRegIfDead(RegisterIdx RootIdx)
Revives original register RootIdx at its original position in the MIR if it was fully rematerialized ...
bool isMOIdenticalAtUses(MachineOperand &MO, ArrayRef< SlotIndex > Uses) const
Determines whether (sub-)register operand MO has the same value at all Uses as at MO.
void transferRegionUsers(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx, unsigned UseRegion)
Transfers all users of register FromRegIdx in region UseRegion to ToRegIdx, the latter of which must ...
void commitRematerializations()
Deletes unused rematerialized registers that were left in the MIR to support rollback.
unsigned getNumRegions() const
Rematerializer(MachineFunction &MF, SmallVectorImpl< RegionBoundaries > &Regions, LiveIntervals &LIS)
Simply initializes some internal state, does not identify rematerialization candidates.
ArrayRef< unsigned > getUnrematableOprds(unsigned RegIdx) const
Returns operand indices corresponding to unrematerializable operands for any register RegIdx.
void transferUser(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx, unsigned UserRegion, MachineInstr &UserMI)
Transfers user UserMI in region UserRegion from register FromRegIdx to ToRegIdx, the latter of which ...
const RegionBoundaries & getRegion(RegisterIdx RegionIdx)
bool isRematerializedRegister(RegisterIdx RegIdx) const
Whether register RegIdx is a rematerialization of some original register.
Printable printRematReg(RegisterIdx RegIdx, bool SkipRegions=false) const
Printable printRegUsers(RegisterIdx RegIdx) const
Printable printUser(const MachineInstr *MI, std::optional< unsigned > UseRegion=std::nullopt) const
void removeListener(Listener *Listen)
Removes a listener from the rematerializer.
RegisterIdx findRematInRegion(RegisterIdx RegIdx, unsigned Region, SlotIndex Before) const
Finds the closest rematerialization of register RegIdx in region Region that exists before slot Befor...
void addListener(Listener *Listen)
Adds a new listener to the rematerializer.
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:66
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition DenseSet.h:291
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
This is an optimization pass for GlobalISel generic memory operations.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
When rematerializating a register (called the "root" register in this context) to a given position,...
DependencyReuseInfo & reuse(RegisterIdx DepIdx)
SmallDenseMap< RegisterIdx, RegisterIdx, 4 > DependencyMap
Keys and values are rematerializable register indices.
DependencyReuseInfo & useRemat(RegisterIdx DepIdx, RegisterIdx DepRematIdx)
unsigned MOIdx
The register's machine operand index in DefMI.
Dependency(unsigned MOIdx, RegisterIdx RegIdx)
RegisterIdx RegIdx
The corresponding register's index in the rematerializer.
A rematerializable register defined by a single machine instruction.
MachineInstr * DefMI
Single MI defining the rematerializable register.
SmallVector< Dependency, 2 > Dependencies
This register's rematerializable dependencies, one per unique rematerializable register operand.
LaneBitmask Mask
The rematerializable register's lane bitmask.
std::pair< MachineInstr *, MachineInstr * > getRegionUseBounds(unsigned UseRegion, const LiveIntervals &LIS) const
Returns the first and last user of the register in region UseRegion.
bool hasUsersOutsideDefRegion() const
unsigned DefRegion
Defining region of DefMI.
SmallDenseMap< unsigned, RegionUsers, 2 > Uses
Uses of the register, mapped by region.
Register getDefReg() const
Returns the rematerializable register from its defining instruction.
SmallDenseSet< MachineInstr *, 4 > RegionUsers