30#define DEBUG_TYPE "rematerializer"
36void Rematerializer::Listener::anchor() {}
49 if ((SR.LaneMask & Mask).none())
51 if (!SR.liveAt(UseIdx))
69 if (
Reg.isPhysical()) {
85 FirstMI ? FirstMI : Regions[UseRegion].second;
112 NewDepRegIdx = RematIdx->second;
123 transferUserImpl(FromRegIdx, ToRegIdx, UserMI);
125 Regs[ToRegIdx].addUser(&UserMI, UserRegion);
126 extendToNewUsers(ToRegIdx, &UserMI);
128 Regs[FromRegIdx].eraseUser(&UserMI, UserRegion);
129 shrinkToUses(FromRegIdx);
134 unsigned UseRegion) {
135 Reg &FromReg = Regs[FromRegIdx];
136 auto UsesIt = FromReg.
Uses.find(UseRegion);
137 if (UsesIt == FromReg.
Uses.end())
143 transferUserImpl(FromRegIdx, ToRegIdx, *UserMI);
147 extendToNewUsers(ToRegIdx, NewUsers);
148 Regs[ToRegIdx].addUsers(RegionUsers, UseRegion);
150 FromReg.
Uses.erase(UseRegion);
151 shrinkToUses(FromRegIdx);
156 Reg &FromReg = Regs[FromRegIdx];
158 for (
const auto &[UseRegion, RegionUsers] : FromReg.
Uses) {
160 transferUserImpl(FromRegIdx, ToRegIdx, *UserMI);
163 Regs[ToRegIdx].addUsers(RegionUsers, UseRegion);
165 extendToNewUsers(ToRegIdx, NewUsers);
167 FromReg.
Uses.clear();
168 deleteReg(FromRegIdx);
171void Rematerializer::transferUserImpl(
RegisterIdx FromRegIdx,
174 assert(FromRegIdx != ToRegIdx &&
"identical registers");
176 "unrelated registers");
188 for (
RegisterIdx &DepRegIdx : Regs[UserRegIdx].Dependencies) {
189 if (DepRegIdx == FromRegIdx) {
190 DepRegIdx = ToRegIdx;
201 LaneBitmask Mask = SubIdx ? TRI.getSubRegIndexLaneMask(SubIdx)
202 : MRI.getMaxLaneMaskForVReg(MO.
getReg());
205 LIS.getInstructionIndex(*MO.
getParent()).getRegSlot(
true),
Uses);
226 if (It == Rematerializations.end())
228 const RematsOf &Remats = It->getSecond();
233 const Reg &RematReg =
getReg(RematRegIdx);
238 if (RematRegSlot < Before &&
239 (BestRegIdx ==
NoReg || RematRegSlot > BestSlot)) {
240 BestSlot = RematRegSlot;
241 BestRegIdx = RematRegIdx;
247void Rematerializer::deleteReg(
RegisterIdx RootIdx) {
257 for (
RegisterIdx DepRegIdx : DeleteReg.Dependencies) {
259 Reg &DepReg = Regs[DepRegIdx];
260 DepReg.eraseUser(DeleteReg.DefMI, DeleteReg.DefRegion);
261 if (DepReg.Uses.empty()) {
266 }
while (!DepDAG.
empty());
270 Reg &DeleteReg = Regs[RegIdx];
271 Register DefReg = DeleteReg.getDefReg();
272 LIS.RemoveMachineInstrFromMaps(*DeleteReg.DefMI);
273 DeleteReg.DefMI->eraseFromParent();
274 DeleteReg.DefMI =
nullptr;
275 LIS.removeInterval(DefReg);
278 SmallSet<RegisterIdx, 8> ShrinkRematRegs;
279 SmallSet<Register, 8> ShrinkUnrematRegs;
285 if (DepReg.isAlive() && ShrinkRematRegs.
insert(DepRegIdx).second) {
286 assert(!DepReg.Uses.empty() &&
"dep should have uses");
287 shrinkToUses(DepRegIdx);
291 if (ShrinkUnrematRegs.
insert(
Reg).second)
292 shrinkToUsesUnremat(
Reg);
297void Rematerializer::DeadDefDelegate::LRE_WillEraseInstruction(
302 Remater.noteMIWillBeDeleted(*
MI);
313 const LiveIntervals &LIS = Remater.LIS;
314 SlotIndex MISlot = LIS.getInstructionIndex(*
MI);
315 unsigned MIRegion = ~0
U;
316 for (
auto [RegionIdx, Bounds] :
enumerate(Remater.Regions)) {
317 auto &[RegionBegin, RegionEnd] = Bounds;
320 if (FirstMI == RegionEnd) {
325 if (LIS.getInstructionIndex(*FirstMI) <= MISlot) {
330 if (LIS.getInstructionIndex(*LastMI) < MISlot)
334 MIRegion = RegionIdx;
335 if (RegionBegin == It)
342 SmallDenseSet<Register, 2> UsedRegs;
343 for (
const MachineOperand &MO :
MI->all_uses()) {
347 auto RematRegUse = Remater.RegToIdx.find(
Reg);
348 if (RematRegUse == Remater.RegToIdx.end())
350 assert(MIRegion != ~0U &&
"remat user cannot be outside regions");
351 Remater.Regs[RematRegUse->second].eraseUser(
MI, MIRegion);
358 Reg &DeleteReg = Remater.Regs[RegIdx];
359 for (
RegisterIdx DepRegIdx : DeleteReg.Dependencies)
360 Remater.Regs[DepRegIdx].eraseUser(
MI, DeleteReg.DefRegion);
362 assert(DeleteReg.isAlive() &&
"register must be alive");
363 assert(DeleteReg.Uses.empty() &&
"register should no longer have uses");
368 Remater.preDeletion(RegIdx);
369 DeleteReg.DefMI =
nullptr;
372void Rematerializer::preDeletion(
RegisterIdx DeleteRegIdx) {
373 Reg &DeleteReg = Regs[DeleteRegIdx];
374 assert(DeleteReg.isAlive() &&
"register must still be alive");
375 noteRegWillBeDeleted(DeleteRegIdx);
382 if (RegionBegin == DeleteReg.DefMI)
390 RematsOf &OriginRemats = Rematerializations.at(OriginIdx);
391 assert(OriginRemats.contains(DeleteRegIdx) &&
"broken remat<->origin link");
392 OriginRemats.erase(DeleteRegIdx);
393 if (OriginRemats.empty())
394 Rematerializations.erase(OriginIdx);
400 : Regions(Regions), MRI(MF.getRegInfo()), LIS(LIS),
401 TII(*MF.getSubtarget().getInstrInfo()), TRI(TII.getRegisterInfo()) {
402#ifdef EXPENSIVE_CHECKS
405 for (
const auto &[RegionBegin, RegionEnd] : Regions) {
406 assert(RegionBegin != RegionEnd &&
"empty region");
407 for (
auto MI = RegionBegin;
MI != RegionEnd; ++
MI) {
408 bool IsNewMI = SeenMIs.
insert(&*
MI).second;
409 assert(IsNewMI &&
"overlapping regions");
410 assert(!
MI->isTerminator() &&
"terminator in region");
412 if (RegionEnd != RegionBegin->getParent()->end()) {
413 bool IsNewMI = SeenMIs.
insert(&*RegionEnd).second;
414 assert(IsNewMI &&
"overlapping regions (upper bound)");
422 UnrematableDeps.clear();
424 Rematerializations.clear();
435 RegionMBB.reserve(Regions.size());
436 for (
unsigned I = 0, E = Regions.size();
I < E; ++
I) {
444 RegionMBB.push_back(&
MBB);
449 assert(!MIRegion.
contains(RegionTerm) &&
"regions should not intersect");
450 MIRegion.
insert({RegionTerm,
I});
454 const unsigned NumVirtRegs = MRI.getNumVirtRegs();
456 for (
unsigned I = 0, E = NumVirtRegs;
I != E; ++
I) {
458 addRegIfRematerializable(
I, MIRegion, SeenRegs);
460 assert(Regs.size() == UnrematableDeps.size());
466 return !Regs.empty();
469void Rematerializer::addRegIfRematerializable(
472 assert(!SeenRegs[VirtRegIdx] &&
"register already seen");
474 SeenRegs.
set(VirtRegIdx);
480 if (!isMIRematerializable(
DefMI))
483 if (DefRegion == MIRegion.
end())
487 RematReg.DefMI = &
DefMI;
488 RematReg.DefRegion = DefRegion->second;
489 unsigned SubIdx =
DefMI.getOperand(0).getSubReg();
490 RematReg.Mask = SubIdx ?
TRI.getSubRegIndexLaneMask(SubIdx)
497 if (
auto UseRegion = MIRegion.
find(&
UseMI); UseRegion != MIRegion.
end())
498 RematReg.addUser(&
UseMI, UseRegion->second);
502 if (RematReg.Uses.empty())
515 if (!SeenRegs[DepRegIdx])
516 addRegIfRematerializable(DepRegIdx, MIRegion, SeenRegs);
517 if (
auto DepIt = RegToIdx.find(DepReg); DepIt != RegToIdx.end()) {
518 RematDeps.
insert(DepIt->second);
520 LaneBitmask &CurrentMask =
523 ? TRI.getSubRegIndexLaneMask(MO.
getSubReg())
524 : MRI.getMaxLaneMaskForVReg(DepReg);
530 RematReg.Dependencies = RematDeps.
takeVector();
531 RegToIdx.
insert({DefReg, Regs.size()});
532 Regs.push_back(RematReg);
533 UnrematableDeps.push_back(UnrematDeps.
takeVector());
536bool Rematerializer::isMIRematerializable(
const MachineInstr &
MI)
const {
537 if (!TII.isReMaterializable(
MI))
540 assert(
MI.getOperand(0).getReg().isVirtual() &&
"should be virtual");
541 assert(MRI.hasOneDef(
MI.getOperand(0).getReg()) &&
"should have single def");
543 for (
const MachineOperand &MO :
MI.all_uses()) {
547 if (MRI.isConstantPhysReg(MO.
getReg()) || TII.isIgnorableUse(MO))
557 if (!
MI.getNumOperands() || !
MI.getOperand(0).isReg() ||
558 MI.getOperand(0).readsReg())
561 auto UserRegIt = RegToIdx.find(
Reg);
562 if (UserRegIt == RegToIdx.end())
564 return UserRegIt->second;
573 Reg &NewReg = Regs.emplace_back();
574 Reg &FromReg = Regs[RegIdx];
583 Origins.push_back(OriginIdx);
584 Rematerializations[OriginIdx].insert(NewRegIdx);
589 TII.reMaterialize(*RegionMBB[UseRegion], InsertPos, NewDefReg, 0,
591 NewReg.
DefMI = &*std::prev(InsertPos);
592 RegToIdx.insert({NewDefReg, NewRegIdx});
593 postRematerialization(RegIdx, NewRegIdx);
595 noteRegCreated(NewRegIdx);
604 assert(RegToIdx.contains(DefReg) &&
"unknown defined register");
605 assert(RegToIdx.at(DefReg) == RegIdx &&
"incorrect defined register");
606 assert(!
getReg(RegIdx).isAlive() &&
"register is still alive");
608 Reg &OriginReg = Regs[RegIdx];
612 if (!RecreateOriginalReg)
613 Rematerializations[
getOriginOf(RegIdx)].insert(RegIdx);
619 if (RecreateOriginalReg) {
620 assert(Rematerializations.contains(RegIdx) &&
"expected remats");
621 ModelRegIdx = *Rematerializations.at(RegIdx).begin();
628 TII.reMaterialize(*RegionMBB[OriginReg.
DefRegion], InsertPos, DefReg, 0,
630 OriginReg.
DefMI = &*std::prev(InsertPos);
631 postRematerialization(ModelRegIdx, RegIdx);
636void Rematerializer::postRematerialization(
RegisterIdx ModelRegIdx,
638 Reg &ModelReg = Regs[ModelRegIdx], &RematReg = Regs[RematRegIdx];
648 RegionBegin = RematReg.DefMI;
652 auto ZipedDeps =
zip_equal(ModelReg.Dependencies, RematReg.Dependencies);
653 for (
const auto &[OldDepRegIdx, NewDepRegIdx] : ZipedDeps) {
655 <<
printID(NewDepRegIdx) <<
'\n');
657 Reg &NewDepReg = Regs[NewDepRegIdx];
658 if (OldDepRegIdx != NewDepRegIdx) {
659 Reg &OldDepReg = Regs[OldDepRegIdx];
660 RematReg.DefMI->substituteRegister(OldDepReg.getDefReg(),
661 NewDepReg.getDefReg(), 0,
TRI);
663 NewDepReg.addUser(RematReg.DefMI, RematReg.DefRegion);
664 extendToNewUsers(NewDepRegIdx, RematReg.DefMI);
670 extendInterval(LIS.getInterval(
Reg), Mask, UseIdx);
673void Rematerializer::extendToNewUsers(
RegisterIdx RegIdx,
675 if (NewUsers.
empty())
678 assert(ExtendReg.isAlive() &&
"register must be alive");
680 Register DefReg = ExtendReg.getDefReg();
681 LiveInterval &LI = LIS.getInterval(DefReg);
682 const LaneBitmask FullLaneMask = MRI.getMaxLaneMaskForVReg(DefReg);
683 const bool ShouldTrackSubReg = MRI.shouldTrackSubRegLiveness(DefReg);
696 for (MachineInstr *UserMI : NewUsers) {
697 SlotIndex UseIdx = LIS.getInstructionIndex(*UserMI).
getRegSlot();
701 for (MachineOperand &MO : UserMI->
all_uses()) {
702 if (MO.
getReg() == DefReg) {
705 RegMask = FullLaneMask;
708 RegMask |= TRI.getSubRegIndexLaneMask(SubIdx);
712 if (RegMask != FullLaneMask) {
715 LIS.getVNInfoAllocator(), RegMask, [](LiveInterval::SubRange &SR) {},
716 *LIS.getSlotIndexes(), TRI);
718 extendInterval(LI, RegMask, UseIdx);
722 if (ExtendReg.DefMI->getOperand(0).isDead())
723 dbgs() <<
"Clearing dead flag for "
726 ExtendReg.DefMI->getOperand(0).setIsDead(
false);
734 <<
printReg(LI.
reg(), &TRI, 0, &MRI) <<
" to " << UseIdx
736 LIS.extendToIndices(LI, UseIdx);
740 bool SubRangeExtended =
false;
741 for (LiveInterval::SubRange &SR : LI.
subranges()) {
742 if ((SR.LaneMask & Mask).any() && !SR.liveAt(UseIdx)) {
743 SubRangeExtended =
true;
744 LLVM_DEBUG(
dbgs() <<
"Extending subrange " << SR <<
" of register "
745 <<
printReg(LI.
reg(), &TRI, 0, &MRI) <<
" to " << UseIdx
747 LIS.extendToIndices(SR, UseIdx);
750 if (!SubRangeExtended)
756 LIS.constructMainRangeFromSubranges(LI);
759void Rematerializer::shrinkToUses(
RegisterIdx RegIdx) {
760 Reg &ShrinkReg = Regs[RegIdx];
761 assert(ShrinkReg.isAlive() &&
"register must be alive");
762 if (ShrinkReg.Uses.empty()) {
769 LiveInterval &LI = LIS.getInterval(ShrinkReg.getDefReg());
772 LIS.shrinkToUses(&LI);
775void Rematerializer::shrinkToUsesUnremat(
Register Reg) {
776 LiveInterval &LI = LIS.getInterval(
Reg);
777 LLVM_DEBUG(
dbgs() <<
"Shrinking interval of unrematerializable register "
780 SmallVector<MachineInstr *, 2> DeadDefs;
781 if (!LIS.shrinkToUses(&LI, &DeadDefs)) {
782 assert(DeadDefs.
empty() &&
"expected no dead def");
788 if (DeadDefs.
empty())
794 DeadDefDelegate DeadDefDeleg(*
this);
795 MachineFunction &MF = *DeadDefs.
front()->getParent()->getParent();
796 LiveRangeEdit(
nullptr, NewRegs, MF, LIS,
nullptr, &DeadDefDeleg)
797 .eliminateDeadDefs(DeadDefs);
800std::pair<MachineInstr *, MachineInstr *>
803 auto It =
Uses.find(UseRegion);
804 if (It ==
Uses.end())
805 return {
nullptr,
nullptr};
811 SlotIndex FirstIndex = LIS.getInstructionIndex(*FirstMI),
812 LastIndex = FirstIndex;
814 while (++
User != UserEnd) {
816 if (UserIndex < FirstIndex) {
817 FirstIndex = UserIndex;
819 }
else if (UserIndex > LastIndex) {
820 LastIndex = UserIndex;
825 return {FirstMI, LastMI};
832void Rematerializer::Reg::addUsers(
const RegionUsers &NewUsers,
839 assert(RUsers.contains(
MI) &&
"user not in region");
840 if (RUsers.size() == 1)
849 std::function<void(
RegisterIdx,
unsigned)> WalkTree =
854 WalkTree(DepRegIdx,
Depth + 1);
856 WalkTree(RootIdx, 0);
861 sort(Regs, [](
const auto &LHS,
const auto &RHS) {
862 return LHS.second > RHS.second;
865 OS <<
printID(RootIdx) <<
" has " << Regs.size() - 1 <<
" dependencies\n";
866 for (
const auto &[RegIdx,
Depth] : Regs) {
877 OS <<
'(' << RegIdx <<
'/';
889 bool SkipRegions)
const {
895 if (!PrintReg.
Uses.empty()) {
896 assert(PrintReg.
isAlive() &&
"dead register cannot have uses");
901 for (
const auto &[
I, Bounds] :
enumerate(Regions)) {
902 if (PrintReg.
Uses.contains(
I))
908 if (LiveIn == Bounds.second) {
916 std::prev(Bounds.second), Bounds.first);
917 if (LI.
liveAt(LIS.getInstructionIndex(*LiveIn)) &&
918 LI.
liveAt(LIS.getInstructionIndex(*LiveOut).getDeadSlot())) {
919 OS << (
First ?
" - " :
",") <<
I;
923 OS << (
First ?
" --> " :
" -> ");
926 auto It = PrintReg.
Uses.begin();
928 while (++It != PrintReg.
Uses.end())
929 OS <<
"," << It->first;
937 LIS.getInstructionIndex(*PrintReg.
DefMI).print(OS);
946 OS <<
" User " <<
printUser(
MI, UseRegion) <<
'\n';
952 std::optional<unsigned> UseRegion)
const {
955 if (RegIdx !=
NoReg) {
966 MI->print(OS,
true,
false,
969 LIS.getInstructionIndex(*MI).print(OS);
978 Rematerializations[Remater.
getOriginOf(RegIdx)].insert(RegIdx);
990 while (ValidPos != ParentMBB->
end() && isRollbackableMI(*ValidPos, Remater))
991 ValidPos = std::next(ValidPos);
998 invalidatePosition(
DefMI, ValidPos);
1004 DeadRegs.push_back(DeadReg(RegIdx, Remater));
1005 const InsertBeforePos InsertPos = makePos(ValidPos, ParentMBB);
1006 PosToIdx[InsertPos].insert(Positions.size());
1007 Positions.push_back(InsertPos);
1019 while (ValidPos != ParentMBB->
end() && isRollbackableMI(*ValidPos, Remater))
1020 ValidPos = std::next(ValidPos);
1021 invalidatePosition(&
MI, ValidPos);
1031 unsigned PositionIndex = Positions.
size();
1037 for (
const DeadReg &Reg :
reverse(DeadRegs)) {
1041 Rematerializations.erase(Reg.Idx);
1050 InsertBeforePos Pos = Positions[--PositionIndex];
1061 if (!Replacements.
insert({Reg.DefMI, RecreateReg.DefMI}).second)
1066 for (
const auto &[RegIdx,
RematsOf] : Rematerializations) {
1080 Rematerializations.clear();
1081 RollingBack =
false;
1094 if (
RematsOf == Rematerializations.end())
1101 const InsertBeforePos MIPos = InsertBeforePos(
MI),
1102 NewPos = makePos(It,
MI->getParent());
1103 auto MIIndices = PosToIdx.find(MIPos);
1104 if (MIIndices == PosToIdx.end())
1107 assert(!InvalIndices.
empty() &&
"no index hold position");
1108 for (
unsigned I : InvalIndices)
1109 Positions[
I] = NewPos;
1110 PosToIdx.try_emplace(NewPos).first->getSecond().insert_range(InvalIndices);
1111 PosToIdx.erase(MIPos);
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.
This file defines the SmallSet class.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
Check if the array is empty.
BitVector & set()
Set all bits in the bitvector.
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)
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.
SubRange * createSubRangeFrom(BumpPtrAllocator &Allocator, LaneBitmask LaneMask, const LiveRange &CopyFrom)
Like createSubRange() but the new range is filled with a copy of the liveness information in CopyFrom...
iterator_range< subrange_iterator > subranges()
LLVM_ABI void refineSubRanges(BumpPtrAllocator &Allocator, LaneBitmask LaneMask, std::function< void(LiveInterval::SubRange &)> Apply, const SlotIndexes &Indexes, const TargetRegisterInfo &TRI, unsigned ComposeSubRegIdx=0)
Refines the subranges to support LaneMask.
SlotIndex InsertMachineInstrInMaps(MachineInstr &MI)
LiveInterval & createAndComputeVirtRegInterval(Register Reg)
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.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
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...
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
VectorType takeVector()
Clear the MapVector and return the underlying vector.
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.
LLVM_ABI 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.
LLVM_ABI Printable printID(RegisterIdx RegIdx) const
LLVM_ABI 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
LLVM_ABI 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.
LLVM_ABI RegisterIdx getDefRegIdx(const MachineInstr &MI) const
If MI's first operand defines a register and that register is a rematerializable register tracked by ...
bool isPermanentlyDead(RegisterIdx RegIdx) const
Determines whether register RegIdx fully disappeared from the MIR.
unsigned RegisterIdx
Index type for rematerializable registers.
LLVM_ABI void recreateReg(RegisterIdx RegIdx, MachineBasicBlock::iterator InsertPos, Register DefReg)
Re-creates a previously deleted register RegIdx before InsertPos, which must be in the register's ori...
LLVM_ABI bool isMOIdenticalAtUses(MachineOperand &MO, ArrayRef< SlotIndex > Uses) const
Determines whether (sub-)register operand MO has the same value at all Uses as at MO.
ArrayRef< std::pair< Register, LaneBitmask > > getUnrematableDeps(RegisterIdx RegIdx) const
Returns unreamaterializable read lanes of register operands for register RegIdx.
LLVM_ABI void transferRegionUsers(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx, unsigned UseRegion)
Transfers all users of register FromRegIdx in region UseRegion to ToRegIdx, the latter of which must ...
LLVM_ABI Rematerializer(MachineFunction &MF, SmallVectorImpl< RegionBoundaries > &Regions, LiveIntervals &LIS)
Simply initializes some internal state, does not identify rematerialization candidates.
LLVM_ABI 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 ...
LLVM_ABI void transferAllUsers(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx)
Transfers all users of register FromRegIdx to register ToRegIdx, the latter of which must be a remate...
LLVM_ABI bool isRegIdenticalAtUses(Register Reg, LaneBitmask Mask, SlotIndex RefSlot, ArrayRef< SlotIndex > Uses) const
Determines whether lanes Mask of register Reg habe the same value at all Uses as at RefSlot.
bool isRematerializedRegister(RegisterIdx RegIdx) const
Whether register RegIdx is a rematerialization of some original register.
LLVM_ABI Printable printRematReg(RegisterIdx RegIdx, bool SkipRegions=false) const
LLVM_ABI Printable printRegUsers(RegisterIdx RegIdx) const
LLVM_ABI Printable printUser(const MachineInstr *MI, std::optional< unsigned > UseRegion=std::nullopt) const
LLVM_ABI RegisterIdx rematerializeReg(RegisterIdx RegIdx, unsigned UseRegion, MachineBasicBlock::iterator InsertPos, SmallVectorImpl< RegisterIdx > &&Dependencies)
Rematerializes register RegIdx before InsertPos in UseRegion, adding the new rematerializable registe...
LLVM_ABI RegisterIdx findRematInRegion(RegisterIdx RegIdx, unsigned Region, SlotIndex Before) const
Finds the closest rematerialization of register RegIdx in region Region that exists before slot Befor...
LLVM_ABI 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 rematerializerNoteRegWillBeDeleted(const Rematerializer &Remater, RegisterIdx RegIdx) override
Called just before register RegIdx is deleted from the MIR.
void rematerializerNoteMIWillBeDeleted(const Rematerializer &Remater, MachineInstr &MI) override
Called just before unrematerializable instruction MI is deleted from the MIR because it has become a ...
void rematerializerNoteRegCreated(const Rematerializer &Remater, RegisterIdx RegIdx) override
Called just after register NewRegIdx is created (following a rematerialization).
Vector takeVector()
Clear the SetVector and return the underlying vector.
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.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
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.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
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,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
IterT skipDebugInstructionsForward(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It until it points to a non-debug instruction or to End and return the resulting iterator.
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
IterT skipDebugInstructionsBackward(IterT It, IterT Begin, bool SkipPseudoOp=true)
Decrement It until it points to a non-debug instruction or to Begin and return the resulting iterator...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
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.
static constexpr LaneBitmask getNone()
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 rematerializable register defined by a single machine instruction.
MachineInstr * DefMI
Single MI defining the rematerializable register.
LaneBitmask Mask
The rematerializable register's lane bitmask.
LLVM_ABI 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.
SmallVector< RegisterIdx, 2 > Dependencies
This register's rematerializable dependencies, one per unique rematerializable register operand.
SmallDenseSet< MachineInstr *, 4 > RegionUsers
A MapVector that performs no allocations if smaller than a certain size.