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/MapVector.h"
18#include "llvm/ADT/STLExtras.h"
25#include <iterator>
26
27namespace llvm {
28
29/// MIR-level target-independent rematerializer. Provides an API to identify and
30/// rematerialize registers within a machine function.
31///
32/// At the moment this supports rematerializing registers that meet all of the
33/// following constraints.
34/// 1. The register is virtual and has a single defining instruction.
35/// 2. The single defining instruction is deemed rematerializable by the TII and
36/// doesn't have any physical register use that is both non-constant and
37/// non-ignorable.
38/// 3. The register has at least one non-debug use that is inside or at a region
39/// boundary (see below for what we consider to be a region).
40///
41/// Rematerializable registers (represented by \ref Rematerializer::Reg) form a
42/// DAG of their own, with every register having incoming edges from all
43/// rematerializable registers which are read by the instruction defining it. It
44/// is possible to rematerialize registers with unrematerializable dependencies;
45/// however the latter are not considered part of this DAG since their
46/// position/identity never change and therefore do not require the same level
47/// of tracking.
48///
49/// Each register has a "dependency DAG" which is defined as the subset of nodes
50/// in the overall DAG that have at least one path to the register, which is
51/// called the "root" register in this context. Semantically, these nodes are
52/// the registers which are involved into the computation of the root register
53/// i.e., all of its transitive dependencies. We use the term "root" because all
54/// paths within the dependency DAG of a register terminate at it; however,
55/// there may be multiple paths between a non-root node and the root node, so a
56/// dependency DAG is not always a tree.
57///
58/// The API uses dense unsigned integers starting at 0 to reference
59/// rematerializable registers. These indices are immutable i.e., even when
60/// registers are deleted their respective integer handle remain valid. Method
61/// which perform actual rematerializations should however be assumed to
62/// invalidate addresses to \ref Rematerializer::Reg objects.
63///
64/// The rematerializer tracks def/use points of registers based on regions.
65/// These are alike the regions the machine scheduler works on. A region is
66/// simply a pair on MBB iterators encoding a range of machine instructions. The
67/// first iterator (beginning of the region) is inclusive whereas the second
68/// iterator (end of the region) is exclusive and can either point to a MBB's
69/// end sentinel or an actual MI (not necessarily a terminator). Regions must be
70/// non-empty, cannot overlap, and cannot contain terminators. However, they do
71/// not have to cover the whole function.
72///
73/// The API uses dense unsigned integers starting at 0 to reference regions.
74/// These map directly to the indices of the corresponding regions in the region
75/// vector passed during construction.
76///
77/// The rematerializer supports rematerializing arbitrary complex DAGs of
78/// registers to regions where these registers are used, with the option of
79/// re-using non-root registers or their previous rematerializations instead of
80/// rematerializing them again.
81///
82/// Throughout its lifetime, the rematerializer tracks new registers it creates
83/// (which are rematerializable by construction) and their relations to other
84/// registers. It performs DAG updates immediately on rematerialization but
85/// defers/batches all necessary live interval updates to reduce the number of
86/// expensive LIS queries when successively rematerializing many registers. \ref
87/// Rematerializer::updateLiveIntervals performs all currently batched live
88/// interval updates.
89///
90/// In its nomenclature, the rematerializer differentiates between "original
91/// registers" (registers that were present when it analyzed the function) and
92/// rematerializations of these original registers. Rematerializations have an
93/// "origin" which is the index of the original regiser they were rematerialized
94/// from (transitivity applies; a rematerialization and all of its own
95/// rematerializations have the same origin). Semantically, only original
96/// registers have rematerializations.
98public:
99 /// Index type for rematerializable registers.
101
102 /// A rematerializable register defined by a single machine instruction.
103 ///
104 /// A rematerializable register has a set of dependencies, which correspond
105 /// to the unique read register operands of its defining instruction.
106 /// They are identified by their machine operand index, and can themselves be
107 /// rematerializable. Operand indices corresponding to unrematerializable
108 /// dependencies are managed by and queried from the rematerializer.
109 ///
110 /// A rematerializable register also has an arbitrary number of users in an
111 /// arbitrary number of regions, potentially including its own defining
112 /// region. When rematerializations lead to operand changes in users, a
113 /// register may find itself without any user left, at which point the
114 /// rematerializer deletes it (setting its defining MI to nullptr).
115 struct Reg {
116 /// Single MI defining the rematerializable register.
118 /// Defining region of \p DefMI.
119 unsigned DefRegion;
120 /// The rematerializable register's lane bitmask.
122
124 /// Uses of the register, mapped by region.
126
127 /// A read register operand of \p DefMI that is rematerializable (according
128 /// to the rematerializer).
129 struct Dependency {
130 /// The register's machine operand index in \p DefMI.
131 unsigned MOIdx;
132 /// The corresponding register's index in the rematerializer.
134
137 };
138 /// This register's rematerializable dependencies, one per unique
139 /// rematerializable register operand.
141
142 /// Returns the rematerializable register from its defining instruction.
144 assert(DefMI && "defining instruction was deleted");
145 assert(DefMI->getOperand(0).isDef() && "not a register def");
146 return DefMI->getOperand(0).getReg();
147 }
148
149 bool hasUsersInDefRegion() const {
150 return !Uses.empty() && Uses.contains(DefRegion);
151 }
152
154 if (Uses.empty())
155 return false;
156 return Uses.size() > 1 || Uses.begin()->first != DefRegion;
157 }
158
159 /// Returns the first and last user of the register in region \p UseRegion.
160 /// If the register has no user in the region, returns a pair of nullptr's.
161 std::pair<MachineInstr *, MachineInstr *>
162 getRegionUseBounds(unsigned UseRegion, const LiveIntervals &LIS) const;
163
164 bool isAlive() const { return DefMI; }
165
166 private:
167 void addUser(MachineInstr *MI, unsigned Region);
168 void addUsers(const RegionUsers &NewUsers, unsigned Region);
169 void eraseUser(MachineInstr *MI, unsigned Region);
170
171 friend Rematerializer;
172 };
173
174 /// Rematerializer listener. Defines overridable hooks that allow to catch
175 /// specific events inside the rematerializer. All hooks do nothing by
176 /// default. Listeners can be added or removed at any time during the
177 /// rematerializer's lifetime.
178 class Listener {
179 public:
181
182 /// Called just after register \p NewRegIdx is created (following a
183 /// rematerialization). At this point the rematerialization exists in the \p
184 /// Remater state and the MIR but does not yet have any user.
185 virtual void rematerializerNoteRegCreated(const Rematerializer &Remater,
186 RegisterIdx NewRegIdx) {}
187
188 /// Called juste before register \p RegIdx is deleted from the MIR. At this
189 /// point the register still exists in the MIR but no longer has any user.
190 virtual void rematerializerNoteRegDeleted(const Rematerializer &Remater,
191 RegisterIdx RegIdx) {}
192
193 virtual ~Listener() = default;
194
195 private:
196 virtual void anchor();
197 };
198
199 /// Error value for register indices.
200 static constexpr unsigned NoReg = ~0;
201
202 /// A region's boundaries i.e. a pair of instruction bundle iterators. The
203 /// lower boundary is inclusive, the upper boundary is exclusive.
205 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>;
206
208
209 /// Simply initializes some internal state, does not identify
210 /// rematerialization candidates.
213 LiveIntervals &LIS);
214
215 /// Goes through the whole MF and identifies all rematerializable registers.
216 /// Returns whether there is any rematerializable register in regions.
217 bool analyze();
218
219 /// Adds a new listener to the rematerializer.
220 void addListener(Listener *Listen) {
221 assert(Listen && "null listener");
222 if (!Listeners.insert(Listen).second)
223 llvm_unreachable("duplicate listener");
224 }
225
226 /// Removes a listener from the rematerializer.
227 void removeListener(Listener *Listen) {
228 if (!Listeners.erase(Listen))
229 llvm_unreachable("unknown listener");
230 }
231
232 /// Removes all listeners from the rematerializer.
233 void clearListeners() { Listeners.clear(); }
234
235 const Reg &getReg(RegisterIdx RegIdx) const {
236 assert(RegIdx < Regs.size() && "out of bounds");
237 return Regs[RegIdx];
238 };
239 ArrayRef<Reg> getRegs() const { return Regs; };
240 unsigned getNumRegs() const { return Regs.size(); };
241
242 const RegionBoundaries &getRegion(RegisterIdx RegionIdx) const {
243 assert(RegionIdx < Regions.size() && "out of bounds");
244 return Regions[RegionIdx];
245 }
246 unsigned getNumRegions() const { return Regions.size(); }
247
248 /// Whether register \p RegIdx is an original register.
249 bool isOriginalRegister(RegisterIdx RegIdx) const {
250 return !isRematerializedRegister(RegIdx);
251 }
252 /// Whether register \p RegIdx is a rematerialization of some original
253 /// register.
255 assert(RegIdx < Regs.size() && "out of bounds");
256 return RegIdx >= UnrematableOprds.size();
257 }
258 /// Returns the origin index of rematerializable register \p RegIdx.
260 assert(isRematerializedRegister(RematRegIdx) && "not a rematerialization");
261 return Origins[RematRegIdx - UnrematableOprds.size()];
262 }
263 /// If \p RegIdx is a rematerialization, returns its origin's index. If it is
264 /// an original register's index, returns the same index.
266 if (isRematerializedRegister(RegIdx))
267 return getOriginOf(RegIdx);
268 return RegIdx;
269 }
270 /// Returns operand indices corresponding to unrematerializable operands for
271 /// any register \p RegIdx.
273 return UnrematableOprds[getOriginOrSelf(RegIdx)];
274 }
275
276 /// If \p MI's first operand defines a register and that register is a
277 /// rematerializable register tracked by the rematerializer, returns its
278 /// index in the \ref Regs vector. Otherwise returns \ref
279 /// Rematerializer::NoReg.
281
282 /// When rematerializating a register (called the "root" register in this
283 /// context) to a given position, we must decide what to do with all its
284 /// rematerializable dependencies (for unrematerializable dependencies, we
285 /// have no choice but to re-use the same register). For each rematerializable
286 /// dependency we can either
287 /// 1. rematerialize it along with the register,
288 /// 2. re-use it as-is, or
289 /// 3. re-use a pre-existing rematerialization of it.
290 /// In case 1, the same decision needs to be made for all of the dependency's
291 /// dependencies. In cases 2 and 3, the dependency's dependencies need not be
292 /// examined.
293 ///
294 /// This struct allows to encode decisions of types (2) and (3) when
295 /// rematerialization of all of the root's dependency DAG is undesirable.
296 /// During rematerialization, registers in the root's dependency DAG which
297 /// have a path to the root made up exclusively of non-re-used registers will
298 /// be rematerialized along with the root.
300 /// Keys and values are rematerializable register indices.
301 ///
302 /// Before rematerialization, this only contains entries for non-root
303 /// registers of the root's dependency DAG which should not be
304 /// rematerialized i.e., for which an existing register should be used
305 /// instead. These map each such non-root register to either the same
306 /// register (case 2, \ref DependencyReuseInfo::reuse) or to a
307 /// rematerialization of the key register (case 3, \ref
308 /// DependencyReuseInfo::useRemat).
309 ///
310 /// After rematerialization, this contains additional entries for non-root
311 /// registers of the root's dependency DAG that needed to be rematerialized
312 /// along the root. These map each such non-root register to their
313 /// corresponding new rematerialization that is used in the rematerialized
314 /// root's dependency DAG. It follows that the difference in map size before
315 /// and after rematerialization indicates the number of non-root registers
316 /// that were rematerialized along the root.
318
320 DependencyMap.insert({DepIdx, DepIdx});
321 return *this;
322 }
324 DependencyMap.insert({DepIdx, DepRematIdx});
325 return *this;
326 }
328 DependencyMap.clear();
329 return *this;
330 }
331 };
332
333 /// Rematerializes register \p RootIdx just before its first user inside
334 /// region \p UseRegion (or at the end of the region if it has no user),
335 /// transfers all its users in the region to the new register, and returns the
336 /// latter's index. The root's dependency DAG is rematerialized or re-used
337 /// according to \p DRI.
338 ///
339 /// When the method returns, \p DRI contains additional entries for non-root
340 /// registers of the root's dependency DAG that needed to be rematerialized
341 /// along the root. References to \ref Rematerializer::Reg should be
342 /// considered invalidated by calls to this method.
343 RegisterIdx rematerializeToRegion(RegisterIdx RootIdx, unsigned UseRegion,
344 DependencyReuseInfo &DRI);
345
346 /// Rematerializes register \p RootIdx before position \p InsertPos in \p
347 /// UseRegion and returns the new register's index. The root's dependency DAG
348 /// is rematerialized or re-used according to \p DRI.
349 ///
350 /// When the method returns, \p DRI contains additional entries for non-root
351 /// registers of the root's dependency DAG that needed to be rematerialized
352 /// along the root. References to \ref Rematerializer::Reg should be
353 /// considered invalidated by calls to this method.
354 RegisterIdx rematerializeToPos(RegisterIdx RootIdx, unsigned UseRegion,
356 DependencyReuseInfo &DRI);
357
358 /// Rematerializes register \p RegIdx before \p InsertPos in \p UseRegion,
359 /// adding the new rematerializable register to the backing vector \ref Regs
360 /// and returning its index inside the vector. Sets the new register's
361 /// rematerializable dependencies to \p Dependencies (these are assumed to
362 /// already exist in the MIR) and its unrematerializable dependencies to the
363 /// same as \p RegIdx. The new register initially has no user. Since the
364 /// method appends to \ref Regs, references to elements within it should be
365 /// considered invalidated across calls to this method unless the vector can
366 /// be guaranteed to have enough space for an extra element.
367 RegisterIdx rematerializeReg(RegisterIdx RegIdx, unsigned UseRegion,
369 SmallVectorImpl<Reg::Dependency> &&Dependencies);
370
371 /// Re-creates a previously deleted register \p RegIdx before \p InsertPos in
372 /// \p DefRegion. \p DefReg must be the original virtual register that \p
373 /// RegIdx used to define. Sets the new register's rematerializable
374 /// dependencies to \p Dependencies (these are assumed to already exist in the
375 /// MIR).
376 void recreateReg(RegisterIdx RegIdx, unsigned DefRegion,
377 MachineBasicBlock::iterator InsertPos, Register DefReg,
378 SmallVectorImpl<Reg::Dependency> &&Dependencies);
379
380 /// Transfers all users of register \p FromRegIdx in region \p UseRegion to \p
381 /// ToRegIdx, the latter of which must be a rematerialization of the former or
382 /// have the same origin register. Users in \p UseRegion must be reachable
383 /// from \p ToRegIdx.
384 void transferRegionUsers(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx,
385 unsigned UseRegion);
386
387 /// Transfers user \p UserMI in region \p UserRegion from register \p
388 /// FromRegIdx to \p ToRegIdx, the latter of which must be a rematerialization
389 /// of the former or have the same origin register. \p UserMI must be a direct
390 /// user of \p FromRegIdx. \p UserMI must be reachable from \p ToRegIdx.
391 void transferUser(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx,
392 unsigned UserRegion, MachineInstr &UserMI);
393
394 /// Transfers all users of register \p FromRegIdx to register \p ToRegIdx, the
395 /// latter of which must be a rematerialization of the former or have the same
396 /// origin register. Users of \p FromRegIdx must be reachable from \p
397 /// ToRegIdx.
398 void transferAllUsers(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx);
399
400 /// Recomputes all live intervals that have changed as a result of previous
401 /// rematerializations.
402 void updateLiveIntervals();
403
404 /// Determines whether (sub-)register operand \p MO has the same value at
405 /// all \p Uses as at \p MO. This implies that it is also available at all \p
406 /// Uses according to its current live interval.
408
409 /// Finds the closest rematerialization of register \p RegIdx in region \p
410 /// Region that exists before slot \p Before. If no such rematerialization
411 /// exists, returns \ref Rematerializer::NoReg.
413 SlotIndex Before) const;
414
416 Printable printID(RegisterIdx RegIdx) const;
417 Printable printRematReg(RegisterIdx RegIdx, bool SkipRegions = false) const;
418 Printable printRegUsers(RegisterIdx RegIdx) const;
420 std::optional<unsigned> UseRegion = std::nullopt) const;
421
422private:
425 LiveIntervals &LIS;
426 const TargetInstrInfo &TII;
427 const TargetRegisterInfo &TRI;
429
430 void noteRegCreated(RegisterIdx RegIdx) const {
431 for (Listener *Listen : Listeners)
432 Listen->rematerializerNoteRegCreated(*this, RegIdx);
433 }
434
435 void noteRegDeleted(RegisterIdx RegIdx) const {
436 for (Listener *Listen : Listeners)
437 Listen->rematerializerNoteRegDeleted(*this, RegIdx);
438 }
439
440 /// Rematerializable registers identified since the rematerializer's creation,
441 /// both dead and alive, originals and rematerializations. No register is ever
442 /// deleted. Indices inside this vector serve as handles for rematerializable
443 /// registers.
444 SmallVector<Reg> Regs;
445 /// For each original register, stores indices of its read register operands
446 /// which are unrematerializable. This doesn't change after the initial
447 /// collection period, so the size of the vector indicates the number of
448 /// original registers.
449 SmallVector<SmallVector<unsigned, 2>> UnrematableOprds;
450 /// Indicates the original register index of each rematerialization, in the
451 /// order in which they are created. The size of the vector indicates the
452 /// total number of rematerializations ever created, including those that were
453 /// deleted.
455 /// Maps original register indices to their currently alive
456 /// rematerializations. In practice most registers don't have
457 /// rematerializations so this is represented as a map to lower memory cost.
458 DenseMap<RegisterIdx, RematsOf> Rematerializations;
459
460 /// Registers mapped to the index of their corresponding rematerialization
461 /// data in the \ref Regs vector. This includes registers that no longer exist
462 /// in the MIR.
463 DenseMap<Register, RegisterIdx> RegToIdx;
464 /// Parent block of each region, in order.
466 /// Set of registers whose live-range may have changed during past
467 /// rematerializations.
468 DenseSet<RegisterIdx> LISUpdates;
469
470 /// Common post-processing step after creating a new register \p RematRegIdx
471 /// at \p InsertPos based on register \p ModelRegIdx.
472 void postRematerialization(RegisterIdx ModelRegIdx, RegisterIdx RematRegIdx,
474
475 /// During the analysis phase, creates a \ref Rematerializer::Reg object for
476 /// virtual register \p VirtRegIdx if it is rematerializable. \p MIRegion maps
477 /// all MIs to their parent region. Set bits in \p SeenRegs indicate virtual
478 /// register indices that have already been visited.
479 void
480 addRegIfRematerializable(unsigned VirtRegIdx,
481 const DenseMap<MachineInstr *, unsigned> &MIRegion,
482 BitVector &SeenRegs);
483
484 /// Determines whether \p MI is considered rematerializable. This further
485 /// restricts constraints imposed by the TII on rematerializable instructions,
486 /// requiring for example that the defined register is virtual and only
487 /// defined once.
488 bool isMIRematerializable(const MachineInstr &MI) const;
489
490 /// Implementation of \ref Rematerializer::transferUser that doesn't update
491 /// register users.
492 void transferUserImpl(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx,
493 MachineInstr &UserMI);
494
495 /// Deletes register \p RootIdx if it no longer has any user. If the register
496 /// is deleted, recursively deletes any of its transitive rematerializable
497 /// dependencies that no longer have users as a result.
498 void deleteRegIfUnused(RegisterIdx RootIdx);
499
500 /// Deletes rematerializable register \p RegIdx from the DAG and relevant
501 /// internal state.
502 void deleteReg(RegisterIdx RegIdx);
503};
504
505/// Rematerializer listener with the ability to re-create deleted registers and
506/// rollback rematerializations. Starts recording register deletions and
507/// rematerializations as soon as it is attached to the rematerializer.
509public:
510 Rollbacker() = default;
511
512 /// Re-creates all deleted registers and rolls back all rematerializations
513 /// that were recorded.
514 void rollback(Rematerializer &Remater);
515
517 RegisterIdx RegIdx) override;
518
520 RegisterIdx RegIdx) override;
521
522private:
523 struct RollbackInfo {
524 /// Original register.
525 Register DefReg;
526 /// Original defining region.
527 unsigned DefRegion;
528 /// Original dependencies.
530 /// Position to re-create the register before in case of rollback. This
531 /// becomes invalid if it originally points to an MI that is deleted later
532 /// as a consequence of other rematerializations. In such cases \ref
533 /// NextRegIdx is guaranteed to be an actual register index from which the
534 /// rollback logic will determine a valid insert position before which to
535 /// re-create this register.
537 /// If \ref InsertPos points to an MI defining a rematerializable register,
538 /// stores its index. Otherwise equals \ref Rematerializer::NoReg.
539 RegisterIdx NextRegIdx;
540
541 RollbackInfo(const Rematerializer &Remater, RegisterIdx RegIdx);
542 };
543
544 /// Original registers that have been deleted, in order of deletion.
546 /// Registers which have been rematerialized (from original index to
547 /// rematerialized index).
549 /// Used to block further recording of events whenver we are actively rolling
550 /// back.
551 bool RollingBack = false;
552};
553
554} // namespace llvm
555
556#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
This file implements a map that provides insertion order iteration.
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,...
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:36
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
MIR-level target-independent rematerializer.
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.
bool isOriginalRegister(RegisterIdx RegIdx) const
Whether register RegIdx is an original register.
static constexpr unsigned NoReg
Error value for register indices.
Printable printID(RegisterIdx RegIdx) const
RegisterIdx rematerializeReg(RegisterIdx RegIdx, unsigned UseRegion, MachineBasicBlock::iterator InsertPos, SmallVectorImpl< Reg::Dependency > &&Dependencies)
Rematerializes register RegIdx before InsertPos in UseRegion, adding the new rematerializable registe...
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...
unsigned getNumRegs() const
SmallDenseSet< RegisterIdx, 4 > RematsOf
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.
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.
RegisterIdx getDefRegIdx(const MachineInstr &MI) const
If MI's first operand defines a register and that register is a rematerializable register tracked by ...
const RegionBoundaries & getRegion(RegisterIdx RegionIdx) const
unsigned RegisterIdx
Index type for rematerializable registers.
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 ...
unsigned getNumRegions() const
Rematerializer(MachineFunction &MF, SmallVectorImpl< RegionBoundaries > &Regions, LiveIntervals &LIS)
Simply initializes some internal state, does not identify rematerialization candidates.
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 ...
ArrayRef< unsigned > getUnrematableOprds(RegisterIdx RegIdx) const
Returns operand indices corresponding to unrematerializable operands for any register RegIdx.
void transferAllUsers(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx)
Transfers all users of register FromRegIdx to register ToRegIdx, the latter of which must be a remate...
bool isRematerializedRegister(RegisterIdx RegIdx) const
Whether register RegIdx is a rematerialization of some original register.
void recreateReg(RegisterIdx RegIdx, unsigned DefRegion, MachineBasicBlock::iterator InsertPos, Register DefReg, SmallVectorImpl< Reg::Dependency > &&Dependencies)
Re-creates a previously deleted register RegIdx before InsertPos in DefRegion.
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.
bool analyze()
Goes through the whole MF and identifies all rematerializable registers.
void rollback(Rematerializer &Remater)
Re-creates all deleted registers and rolls back all rematerializations that were recorded.
Rollbacker()=default
void rematerializerNoteRegCreated(const Rematerializer &Remater, RegisterIdx RegIdx) override
Called just after register NewRegIdx is created (following a rematerialization).
void rematerializerNoteRegDeleted(const Rematerializer &Remater, RegisterIdx RegIdx) override
Called juste before register RegIdx is deleted from the MIR.
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...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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