28#define DEBUG_TYPE "rematerializer"
34void Rematerializer::Listener::anchor() {}
47 if ((SR.LaneMask & Mask).none())
49 if (!SR.liveAt(UseIdx))
67 if (
Reg.isPhysical()) {
83 FirstMI ? FirstMI : Regions[UseRegion].second;
110 NewDepRegIdx = RematIdx->second;
121 transferUserImpl(FromRegIdx, ToRegIdx, UserMI);
122 Regs[FromRegIdx].eraseUser(&UserMI, UserRegion);
123 Regs[ToRegIdx].addUser(&UserMI, UserRegion);
124 deleteRegIfUnused(FromRegIdx);
129 unsigned UseRegion) {
130 auto &FromRegUsers = Regs[FromRegIdx].Uses;
131 auto UsesIt = FromRegUsers.find(UseRegion);
132 if (UsesIt == FromRegUsers.end())
137 transferUserImpl(FromRegIdx, ToRegIdx, *UserMI);
138 Regs[ToRegIdx].addUsers(RegionUsers, UseRegion);
139 FromRegUsers.erase(UseRegion);
140 deleteRegIfUnused(FromRegIdx);
145 Reg &FromReg = Regs[FromRegIdx], &ToReg = Regs[ToRegIdx];
146 for (
const auto &[UseRegion, RegionUsers] : FromReg.
Uses) {
148 transferUserImpl(FromRegIdx, ToRegIdx, *UserMI);
149 ToReg.addUsers(RegionUsers, UseRegion);
151 FromReg.
Uses.clear();
152 deleteRegIfUnused(FromRegIdx);
155void Rematerializer::transferUserImpl(
RegisterIdx FromRegIdx,
158 assert(FromRegIdx != ToRegIdx &&
"identical registers");
160 "unrelated registers");
167 LISUpdates.insert(FromRegIdx);
168 LISUpdates.insert(ToRegIdx);
174 for (Reg::Dependency &Dep : Regs[UserRegIdx].Dependencies) {
175 if (Dep.RegIdx == FromRegIdx) {
176 Dep.RegIdx = ToRegIdx;
191 if (LIS.hasInterval(DefReg))
192 LIS.removeInterval(DefReg);
196 LIS.createAndComputeVirtRegInterval(DefReg);
199 dbgs() <<
"Re-computed interval for " <<
printID(RegIdx) <<
": ";
200 LIS.getInterval(DefReg).print(
dbgs());
207 if (!SeenUnrematRegs.
insert(UnrematReg).second)
209 LIS.removeInterval(UnrematReg);
210 bool NeedSplit =
false;
218 LIS.createAndComputeVirtRegInterval(UnrematReg, NeedSplit);
221 LIS.splitSeparateComponents(LI, SplitLIs);
224 dbgs() <<
" Re-computed interval for register "
240 LaneBitmask Mask = SubIdx ? TRI.getSubRegIndexLaneMask(SubIdx)
241 : MRI.getMaxLaneMaskForVReg(
Reg);
256 if (It == Rematerializations.end())
258 const RematsOf &Remats = It->getSecond();
263 const Reg &RematReg =
getReg(RematRegIdx);
268 if (RematRegSlot < Before &&
269 (BestRegIdx ==
NoReg || RematRegSlot > BestSlot)) {
270 BestSlot = RematRegSlot;
271 BestRegIdx = RematRegIdx;
277void Rematerializer::deleteRegIfUnused(
RegisterIdx RootIdx) {
285 DeleteOrder.
insert(RootIdx);
289 for (
const Reg::Dependency &Dep : DeleteReg.Dependencies) {
291 Reg &DepReg = Regs[Dep.RegIdx];
292 DepReg.eraseUser(DeleteReg.DefMI, DeleteReg.DefRegion);
293 if (DepReg.Uses.empty()) {
294 DeleteOrder.
insert(Dep.RegIdx);
298 }
while (!DepDAG.
empty());
301 Reg &DeleteReg = Regs[RegIdx];
305 Register DefReg = DeleteReg.getDefReg();
306 if (LIS.hasInterval(DefReg))
307 LIS.removeInterval(DefReg);
308 LISUpdates.erase(RegIdx);
314 RematsOf &OriginRemats = Rematerializations.at(OriginIdx);
315 assert(OriginRemats.contains(RegIdx) &&
"broken remat<->origin link");
316 OriginRemats.erase(RegIdx);
317 if (OriginRemats.empty())
318 Rematerializations.erase(OriginIdx);
324void Rematerializer::deleteReg(
RegisterIdx RegIdx) {
325 noteRegDeleted(RegIdx);
327 Reg &DeleteReg = Regs[RegIdx];
328 assert(DeleteReg.DefMI &&
"register was already deleted");
332 if (RegionBegin == DeleteReg.DefMI)
334 LIS.RemoveMachineInstrFromMaps(*DeleteReg.DefMI);
335 DeleteReg.DefMI->eraseFromParent();
336 DeleteReg.DefMI =
nullptr;
342 : Regions(Regions), MRI(MF.getRegInfo()), LIS(LIS),
343 TII(*MF.getSubtarget().getInstrInfo()), TRI(TII.getRegisterInfo()) {
344#ifdef EXPENSIVE_CHECKS
347 for (
const auto &[RegionBegin, RegionEnd] : Regions) {
348 assert(RegionBegin != RegionEnd &&
"empty region");
349 for (
auto MI = RegionBegin;
MI != RegionEnd; ++
MI) {
350 bool IsNewMI = SeenMIs.
insert(&*
MI).second;
351 assert(IsNewMI &&
"overlapping regions");
352 assert(!
MI->isTerminator() &&
"terminator in region");
354 if (RegionEnd != RegionBegin->getParent()->end()) {
355 bool IsNewMI = SeenMIs.
insert(&*RegionEnd).second;
356 assert(IsNewMI &&
"overlapping regions (upper bound)");
364 UnrematableOprds.clear();
366 Rematerializations.clear();
378 RegionMBB.
reserve(Regions.size());
379 for (
unsigned I = 0, E = Regions.size();
I < E; ++
I) {
387 RegionMBB.push_back(&
MBB);
392 assert(!MIRegion.
contains(RegionTerm) &&
"regions should not intersect");
393 MIRegion.
insert({RegionTerm,
I});
397 const unsigned NumVirtRegs = MRI.getNumVirtRegs();
399 for (
unsigned I = 0, E = NumVirtRegs;
I != E; ++
I) {
401 addRegIfRematerializable(
I, MIRegion, SeenRegs);
403 assert(Regs.size() == UnrematableOprds.size());
409 return !Regs.empty();
412void Rematerializer::addRegIfRematerializable(
415 assert(!SeenRegs[VirtRegIdx] &&
"register already seen");
417 SeenRegs.
set(VirtRegIdx);
423 if (!isMIRematerializable(
DefMI))
426 if (DefRegion == MIRegion.
end())
430 RematReg.DefMI = &
DefMI;
431 RematReg.DefRegion = DefRegion->second;
432 unsigned SubIdx =
DefMI.getOperand(0).getSubReg();
433 RematReg.Mask = SubIdx ?
TRI.getSubRegIndexLaneMask(SubIdx)
440 if (
auto UseRegion = MIRegion.
find(&
UseMI); UseRegion != MIRegion.
end())
441 RematReg.addUser(&
UseMI, UseRegion->second);
445 if (RematReg.Uses.empty())
452 for (
const auto &[MOIdx, MO] :
enumerate(RematReg.DefMI->operands())) {
454 if (!DepReg || !AllDepRegs.
insert(DepReg).second)
457 if (!SeenRegs[DepRegIdx])
458 addRegIfRematerializable(DepRegIdx, MIRegion, SeenRegs);
459 if (
auto DepIt = RegToIdx.find(DepReg); DepIt != RegToIdx.end())
460 RematReg.Dependencies.push_back(Reg::Dependency(MOIdx, DepIt->second));
466 RegToIdx.
insert({DefReg, Regs.size()});
467 Regs.push_back(RematReg);
468 UnrematableOprds.push_back(UnrematDeps);
471bool Rematerializer::isMIRematerializable(
const MachineInstr &
MI)
const {
472 if (!TII.isReMaterializable(
MI))
475 assert(
MI.getOperand(0).getReg().isVirtual() &&
"should be virtual");
476 assert(MRI.hasOneDef(
MI.getOperand(0).getReg()) &&
"should have single def");
478 for (
const MachineOperand &MO :
MI.all_uses()) {
482 if (MRI.isConstantPhysReg(MO.
getReg()) || TII.isIgnorableUse(MO))
492 if (!
MI.getNumOperands() || !
MI.getOperand(0).isReg() ||
493 MI.getOperand(0).readsReg())
496 auto UserRegIt = RegToIdx.find(
Reg);
497 if (UserRegIt == RegToIdx.end())
499 return UserRegIt->second;
508 Reg &NewReg = Regs.emplace_back();
509 Reg &FromReg = Regs[RegIdx];
518 Origins.push_back(OriginIdx);
519 Rematerializations[OriginIdx].insert(NewRegIdx);
524 TII.reMaterialize(*RegionMBB[UseRegion], InsertPos, NewDefReg, 0,
526 NewReg.
DefMI = &*std::prev(InsertPos);
527 RegToIdx.insert({NewDefReg, NewRegIdx});
528 postRematerialization(RegIdx, NewRegIdx, InsertPos);
530 noteRegCreated(NewRegIdx);
540 assert(RegToIdx.contains(DefReg) &&
"unknown defined register");
541 assert(RegToIdx.at(DefReg) == RegIdx &&
"incorrect defined register");
544 Reg &OriginReg = Regs[RegIdx];
550 if (!RecreateOriginalReg)
551 Rematerializations[
getOriginOf(RegIdx)].insert(RegIdx);
557 if (RecreateOriginalReg) {
558 assert(Rematerializations.contains(RegIdx) &&
"expected remats");
559 ModelRegIdx = *Rematerializations.at(RegIdx).begin();
566 TII.reMaterialize(*RegionMBB[DefRegion], InsertPos, DefReg, 0, ModelDefMI);
567 OriginReg.
DefMI = &*std::prev(InsertPos);
568 postRematerialization(ModelRegIdx, RegIdx, InsertPos);
573void Rematerializer::postRematerialization(
578 Reg &ModelReg = Regs[ModelRegIdx], &RematReg = Regs[RematRegIdx];
582 RegionBegin = RematReg.DefMI;
586 auto ZipedDeps =
zip_equal(ModelReg.Dependencies, RematReg.Dependencies);
587 for (
const auto &[OldDep, NewDep] : ZipedDeps) {
588 assert(OldDep.MOIdx == NewDep.MOIdx &&
"operand mismatch");
590 <<
printID(OldDep.RegIdx) <<
" -> "
591 <<
printID(NewDep.RegIdx) <<
'\n');
593 Reg &NewDepReg = Regs[NewDep.RegIdx];
594 if (OldDep.RegIdx != NewDep.RegIdx) {
595 Register OldDefReg = ModelReg.DefMI->getOperand(OldDep.MOIdx).getReg();
596 RematReg.DefMI->substituteRegister(OldDefReg, NewDepReg.getDefReg(), 0,
598 LISUpdates.insert(OldDep.RegIdx);
600 NewDepReg.addUser(RematReg.DefMI, RematReg.DefRegion);
601 LISUpdates.insert(NewDep.RegIdx);
605std::pair<MachineInstr *, MachineInstr *>
608 auto It =
Uses.find(UseRegion);
609 if (It ==
Uses.end())
610 return {
nullptr,
nullptr};
616 SlotIndex FirstIndex = LIS.getInstructionIndex(*FirstMI),
617 LastIndex = FirstIndex;
619 while (++
User != UserEnd) {
621 if (UserIndex < FirstIndex) {
622 FirstIndex = UserIndex;
624 }
else if (UserIndex > LastIndex) {
625 LastIndex = UserIndex;
630 return {FirstMI, LastMI};
637void Rematerializer::Reg::addUsers(
const RegionUsers &NewUsers,
644 assert(RUsers.contains(
MI) &&
"user not in region");
645 if (RUsers.size() == 1)
654 std::function<void(
RegisterIdx,
unsigned)> WalkTree =
659 WalkTree(Dep.RegIdx,
Depth + 1);
661 WalkTree(RootIdx, 0);
666 sort(Regs, [](
const auto &LHS,
const auto &RHS) {
667 return LHS.second > RHS.second;
670 OS <<
printID(RootIdx) <<
" has " << Regs.size() - 1 <<
" dependencies\n";
671 for (
const auto &[RegIdx,
Depth] : Regs) {
682 OS <<
'(' << RegIdx <<
'/';
683 if (!PrintReg.
DefMI) {
694 bool SkipRegions)
const {
699 if (!PrintReg.
Uses.empty()) {
700 assert(PrintReg.
DefMI &&
"dead register cannot have uses");
705 for (
const auto [
I, Bounds] :
enumerate(Regions)) {
706 if (Bounds.first == Bounds.second)
708 if (!PrintReg.
Uses.contains(
I) &&
709 LI.
liveAt(LIS.getInstructionIndex(*Bounds.first)) &&
710 LI.
liveAt(LIS.getInstructionIndex(*std::prev(Bounds.second))
712 OS << (
First ?
" - " :
",") <<
I;
716 OS << (
First ?
" --> " :
" -> ");
719 auto It = PrintReg.
Uses.begin();
721 while (++It != PrintReg.
Uses.end())
722 OS <<
"," << It->first;
730 LIS.getInstructionIndex(*PrintReg.
DefMI).print(OS);
738 OS <<
" User " <<
printUser(
MI, UseRegion) <<
'\n';
744 std::optional<unsigned> UseRegion)
const {
747 if (RegIdx !=
NoReg) {
758 MI->print(OS,
true,
false,
761 LIS.getInstructionIndex(*MI).print(OS);
765Rollbacker::RollbackInfo::RollbackInfo(
const Rematerializer &Remater,
768 DefReg = Reg.getDefReg();
769 DefRegion = Reg.DefRegion;
770 Dependencies = Reg.Dependencies;
772 InsertPos = std::next(Reg.DefMI->getIterator());
773 if (InsertPos != Reg.DefMI->getParent()->end())
783 Rematerializations[Remater.
getOriginOf(RegIdx)].insert(RegIdx);
790 DeadRegs.try_emplace(RegIdx, Remater, RegIdx);
797 for (
auto &[RegIdx, Info] : DeadRegs) {
807 const auto *NextRegRollback = DeadRegs.find(NextRegIdx);
808 if (NextRegRollback == DeadRegs.end())
810 InsertPos = NextRegRollback->second.InsertPos;
811 NextRegIdx = NextRegRollback->second.NextRegIdx;
813 Remater.
recreateReg(RegIdx, Info.DefRegion, InsertPos, Info.DefReg,
814 std::move(Info.Dependencies));
818 for (
const auto &[RegIdx,
RematsOf] : Rematerializations) {
831 Rematerializations.clear();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
iv Induction Variable Users
Register const TargetRegisterInfo * TRI
This file implements a map that provides insertion order iteration.
Promote Memory to Register
Rematerializer::RegisterIdx RegisterIdx
static Register getRegDependency(const MachineOperand &MO)
If MO is a virtual read register, returns it.
static bool isIdenticalAtUse(const VNInfo &OVNI, LaneBitmask Mask, SlotIndex UseIdx, const LiveInterval &LI)
Checks whether the value in LI at UseIdx is identical to OVNI (this implies it is also live there).
MIR-level target-independent rematerialization helpers.
Remove Loads Into Fake Uses
This file implements a set that has insertion order iteration characteristics.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > emplace_or_assign(const KeyT &Key, Ts &&...Args)
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Implements a dense probed hash-table based set.
A live range for subregisters.
LiveInterval - This class represents the liveness of a register, or stack slot.
bool hasSubRanges() const
Returns true if subregister liveness information is available.
iterator_range< subrange_iterator > subranges()
SlotIndex InsertMachineInstrInMaps(MachineInstr &MI)
bool liveAt(SlotIndex index) const
VNInfo * getVNInfoAt(SlotIndex Idx) const
getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
MachineInstrBundleIterator< MachineInstr > iterator
Representation of each machine instruction.
LLVM_ABI void substituteRegister(Register FromReg, Register ToReg, unsigned SubIdx, const TargetRegisterInfo &RegInfo)
Replace all occurrences of FromReg with ToReg:SubIdx, properly composing subreg indices where necessa...
LLVM_ABI void print(raw_ostream &OS, bool IsStandalone=true, bool SkipOpers=false, bool SkipDebugLoc=false, bool AddNewLine=true, const TargetInstrInfo *TII=nullptr) const
Print this MI to OS.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool readsReg() const
readsReg - Returns true if this operand reads the previous value of its register.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
Register getReg() const
getReg - Returns the register number.
MachineOperand * getOneDef(Register Reg) const
Returns the defining operand if there is exactly one operand defining the specified register,...
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
LLVM_ABI LaneBitmask getMaxLaneMaskForVReg(Register Reg) const
Returns a mask covering all bits that can appear in lane masks of subregisters of the virtual registe...
Simple wrapper around std::function<void(raw_ostream&)>.
RegionT * getParent() const
Get the parent of the Region.
Wrapper class representing virtual and physical registers.
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
unsigned virtRegIndex() const
Convert a virtual register number to a 0-based index.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Rematerializer::RegisterIdx RegisterIdx
MIR-level target-independent rematerializer.
Printable printDependencyDAG(RegisterIdx RootIdx) const
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...
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 ...
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 ...
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
RegisterIdx findRematInRegion(RegisterIdx RegIdx, unsigned Region, SlotIndex Before) const
Finds the closest rematerialization of register RegIdx in region Region that exists before slot Befor...
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.
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.
bool insert(const value_type &X)
Insert a new element into the SetVector.
SlotIndex - An opaque wrapper around machine indexes.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
Implements a dense probed hash-table based set with some number of buckets stored inline.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A Use represents the edge between a Value definition and its users.
VNInfo - Value Number Information.
std::pair< iterator, bool > insert(const ValueT &V)
This class implements an extremely fast bulk output stream that can only output to a stream.
#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.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
When rematerializating a register (called the "root" register in this context) to a given position,...
SmallDenseMap< RegisterIdx, RegisterIdx, 4 > DependencyMap
Keys and values are rematerializable register indices.
A read register operand of DefMI that is rematerializable (according to 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.
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