LLVM 23.0.0git
Rematerializer.cpp
Go to the documentation of this file.
1//=====-- Rematerializer.cpp - 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/// Implements helpers for target-independent rematerialization at the MIR
11/// level.
12//
13//===----------------------------------------------------------------------===//
14
16#include "llvm/ADT/MapVector.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/SetVector.h"
25#include "llvm/Support/Debug.h"
26#include <optional>
27
28#define DEBUG_TYPE "rematerializer"
29
30using namespace llvm;
32
33// Pin the vtable to this file.
34void Rematerializer::Listener::anchor() {}
35
36/// Checks whether the value in \p LI at \p UseIdx is identical to \p OVNI (this
37/// implies it is also live there). When \p LI has sub-ranges, checks that
38/// all sub-ranges intersecting with \p Mask are also live at \p UseIdx.
39static bool isIdenticalAtUse(const VNInfo &OVNI, LaneBitmask Mask,
40 SlotIndex UseIdx, const LiveInterval &LI) {
41 if (&OVNI != LI.getVNInfoAt(UseIdx))
42 return false;
43
44 if (LI.hasSubRanges()) {
45 // Check that intersecting subranges are live at user.
46 for (const LiveInterval::SubRange &SR : LI.subranges()) {
47 if ((SR.LaneMask & Mask).none())
48 continue;
49 if (!SR.liveAt(UseIdx))
50 return false;
51
52 // Early exit if all used lanes are checked. No need to continue.
53 Mask &= ~SR.LaneMask;
54 if (Mask.none())
55 break;
56 }
57 }
58 return true;
59}
60
61/// If \p MO is a virtual read register, returns it. Otherwise returns the
62/// sentinel register.
64 if (!MO.isReg() || !MO.readsReg())
65 return Register();
66 Register Reg = MO.getReg();
67 if (Reg.isPhysical()) {
68 // By the requirements on trivially rematerializable instructions, a
69 // physical register use is either constant or ignorable.
70 return Register();
71 }
72 return Reg;
73}
74
76 unsigned UseRegion,
78 MachineInstr *FirstMI =
79 getReg(RootIdx).getRegionUseBounds(UseRegion, LIS).first;
80 // If there are no users in the region, rematerialize the register at the very
81 // end of the region.
83 FirstMI ? FirstMI : Regions[UseRegion].second;
84 RegisterIdx NewRegIdx =
85 rematerializeToPos(RootIdx, UseRegion, InsertPos, DRI);
86 transferRegionUsers(RootIdx, NewRegIdx, UseRegion);
87 return NewRegIdx;
88}
89
94 assert(!DRI.DependencyMap.contains(RootIdx));
95 LLVM_DEBUG(dbgs() << "Rematerializing " << printID(RootIdx) << '\n');
96
98 // Copy all dependencies because recursive rematerialization of dependencies
99 // may invalidate references to the backing vector of registers.
100 SmallVector<Reg::Dependency, 2> OldDeps(getReg(RootIdx).Dependencies);
101 for (const Reg::Dependency &Dep : OldDeps) {
102 // Recursively rematerialize required dependencies at the same position as
103 // the root. Registers form a DAG so the recursion is guaranteed to
104 // terminate.
105 auto RematIdx = DRI.DependencyMap.find(Dep.RegIdx);
106 RegisterIdx NewDepRegIdx;
107 if (RematIdx == DRI.DependencyMap.end())
108 NewDepRegIdx = rematerializeToPos(Dep.RegIdx, UseRegion, InsertPos, DRI);
109 else
110 NewDepRegIdx = RematIdx->second;
111 NewDeps.emplace_back(Dep.MOIdx, NewDepRegIdx);
112 }
113 RegisterIdx NewIdx =
114 rematerializeReg(RootIdx, UseRegion, InsertPos, std::move(NewDeps));
115 DRI.DependencyMap.insert({RootIdx, NewIdx});
116 return NewIdx;
117}
118
120 unsigned UserRegion, MachineInstr &UserMI) {
121 transferUserImpl(FromRegIdx, ToRegIdx, UserMI);
122 Regs[FromRegIdx].eraseUser(&UserMI, UserRegion);
123 Regs[ToRegIdx].addUser(&UserMI, UserRegion);
124 deleteRegIfUnused(FromRegIdx);
125}
126
128 RegisterIdx ToRegIdx,
129 unsigned UseRegion) {
130 auto &FromRegUsers = Regs[FromRegIdx].Uses;
131 auto UsesIt = FromRegUsers.find(UseRegion);
132 if (UsesIt == FromRegUsers.end())
133 return;
134
135 const SmallDenseSet<MachineInstr *, 4> &RegionUsers = UsesIt->getSecond();
136 for (MachineInstr *UserMI : RegionUsers)
137 transferUserImpl(FromRegIdx, ToRegIdx, *UserMI);
138 Regs[ToRegIdx].addUsers(RegionUsers, UseRegion);
139 FromRegUsers.erase(UseRegion);
140 deleteRegIfUnused(FromRegIdx);
141}
142
144 RegisterIdx ToRegIdx) {
145 Reg &FromReg = Regs[FromRegIdx], &ToReg = Regs[ToRegIdx];
146 for (const auto &[UseRegion, RegionUsers] : FromReg.Uses) {
147 for (MachineInstr *UserMI : RegionUsers)
148 transferUserImpl(FromRegIdx, ToRegIdx, *UserMI);
149 ToReg.addUsers(RegionUsers, UseRegion);
150 }
151 FromReg.Uses.clear();
152 deleteRegIfUnused(FromRegIdx);
153}
154
155void Rematerializer::transferUserImpl(RegisterIdx FromRegIdx,
156 RegisterIdx ToRegIdx,
157 MachineInstr &UserMI) {
158 assert(FromRegIdx != ToRegIdx && "identical registers");
159 assert(getOriginOrSelf(FromRegIdx) == getOriginOrSelf(ToRegIdx) &&
160 "unrelated registers");
161
162 LLVM_DEBUG(dbgs() << "User transfer from " << printID(FromRegIdx) << " to "
163 << printID(ToRegIdx) << ": " << printUser(&UserMI) << '\n');
164
165 UserMI.substituteRegister(getReg(FromRegIdx).getDefReg(),
166 getReg(ToRegIdx).getDefReg(), 0, TRI);
167 LISUpdates.insert(FromRegIdx);
168 LISUpdates.insert(ToRegIdx);
169
170 // If the user is rematerializable, we must change its dependency to the
171 // new register.
172 if (RegisterIdx UserRegIdx = getDefRegIdx(UserMI); UserRegIdx != NoReg) {
173 // Look for the user's dependency that matches the register.
174 for (Reg::Dependency &Dep : Regs[UserRegIdx].Dependencies) {
175 if (Dep.RegIdx == FromRegIdx) {
176 Dep.RegIdx = ToRegIdx;
177 return;
178 }
179 }
180 llvm_unreachable("broken dependency");
181 }
182}
183
185 DenseSet<Register> SeenUnrematRegs;
186 for (RegisterIdx RegIdx : LISUpdates) {
187 const Reg &UpdateReg = getReg(RegIdx);
188 assert(UpdateReg.isAlive() && "dead register");
189
190 Register DefReg = UpdateReg.getDefReg();
191 if (LIS.hasInterval(DefReg))
192 LIS.removeInterval(DefReg);
193 // Rematerializable registers have a single definition by construction so
194 // re-creating their interval cannot yield a live interval with multiple
195 // connected components.
196 LIS.createAndComputeVirtRegInterval(DefReg);
197
198 LLVM_DEBUG({
199 dbgs() << "Re-computed interval for " << printID(RegIdx) << ": ";
200 LIS.getInterval(DefReg).print(dbgs());
201 dbgs() << '\n' << printRegUsers(RegIdx);
202 });
203
204 // Update intervals for unrematerializable operands.
205 for (unsigned MOIdx : getUnrematableOprds(RegIdx)) {
206 Register UnrematReg = UpdateReg.DefMI->getOperand(MOIdx).getReg();
207 if (!SeenUnrematRegs.insert(UnrematReg).second)
208 continue;
209 LIS.removeInterval(UnrematReg);
210 bool NeedSplit = false;
211
212 // Unrematerializable registers may end up with multiple connected
213 // components in their live interval after it is re-created. It needs to
214 // be split in such cases. We don't track unrematerializable registers by
215 // their actual register index (just by operand index) so we do not need
216 // to update any state in the rematerializer.
217 LiveInterval &LI =
218 LIS.createAndComputeVirtRegInterval(UnrematReg, NeedSplit);
219 if (NeedSplit) {
221 LIS.splitSeparateComponents(LI, SplitLIs);
222 }
224 dbgs() << " Re-computed interval for register "
225 << printReg(UnrematReg, &TRI,
226 UpdateReg.DefMI->getOperand(MOIdx).getSubReg(),
227 &MRI)
228 << '\n');
229 }
230 }
231 LISUpdates.clear();
232}
233
236 if (Uses.empty())
237 return true;
238 Register Reg = MO.getReg();
239 unsigned SubIdx = MO.getSubReg();
240 LaneBitmask Mask = SubIdx ? TRI.getSubRegIndexLaneMask(SubIdx)
241 : MRI.getMaxLaneMaskForVReg(Reg);
242 const LiveInterval &LI = LIS.getInterval(Reg);
243 const VNInfo *DefVN =
244 LI.getVNInfoAt(LIS.getInstructionIndex(*MO.getParent()).getRegSlot(true));
245 for (SlotIndex Use : Uses) {
246 if (!isIdenticalAtUse(*DefVN, Mask, Use, LI))
247 return false;
248 }
249 return true;
250}
251
253 unsigned Region,
254 SlotIndex Before) const {
255 auto It = Rematerializations.find(getOriginOrSelf(RegIdx));
256 if (It == Rematerializations.end())
257 return NoReg;
258 const RematsOf &Remats = It->getSecond();
259
260 SlotIndex BestSlot;
261 RegisterIdx BestRegIdx = NoReg;
262 for (RegisterIdx RematRegIdx : Remats) {
263 const Reg &RematReg = getReg(RematRegIdx);
264 if (RematReg.DefRegion != Region || RematReg.Uses.empty())
265 continue;
266 SlotIndex RematRegSlot =
267 LIS.getInstructionIndex(*RematReg.DefMI).getRegSlot();
268 if (RematRegSlot < Before &&
269 (BestRegIdx == NoReg || RematRegSlot > BestSlot)) {
270 BestSlot = RematRegSlot;
271 BestRegIdx = RematRegIdx;
272 }
273 }
274 return BestRegIdx;
275}
276
277void Rematerializer::deleteRegIfUnused(RegisterIdx RootIdx) {
278 if (!getReg(RootIdx).Uses.empty())
279 return;
280
281 // Traverse the root's dependency DAG depth-first to find the set of registers
282 // we can delete and a legal order to delete them in.
283 SmallVector<RegisterIdx, 4> DepDAG{RootIdx};
285 DeleteOrder.insert(RootIdx);
286 do {
287 // A deleted register's dependencies may be deletable too.
288 const Reg &DeleteReg = getReg(DepDAG.pop_back_val());
289 for (const Reg::Dependency &Dep : DeleteReg.Dependencies) {
290 // All dependencies loose a user (the deleted register).
291 Reg &DepReg = Regs[Dep.RegIdx];
292 DepReg.eraseUser(DeleteReg.DefMI, DeleteReg.DefRegion);
293 if (DepReg.Uses.empty()) {
294 DeleteOrder.insert(Dep.RegIdx);
295 DepDAG.push_back(Dep.RegIdx);
296 }
297 }
298 } while (!DepDAG.empty());
299
300 for (RegisterIdx RegIdx : reverse(DeleteOrder)) {
301 Reg &DeleteReg = Regs[RegIdx];
302
303 // It is possible that the defined register we are deleting doesn't have an
304 // interval yet if the LIS hasn't been updated since it was created.
305 Register DefReg = DeleteReg.getDefReg();
306 if (LIS.hasInterval(DefReg))
307 LIS.removeInterval(DefReg);
308 LISUpdates.erase(RegIdx);
309
310 deleteReg(RegIdx);
311 if (isRematerializedRegister(RegIdx)) {
312 // Delete rematerialized register from its origin's rematerializations.
313 RematsOf &OriginRemats = Rematerializations.at(getOriginOf(RegIdx));
314 assert(OriginRemats.contains(RegIdx) && "broken remat<->origin link");
315 OriginRemats.erase(RegIdx);
316 if (OriginRemats.empty())
317 Rematerializations.erase(RegIdx);
318 }
319 LLVM_DEBUG(dbgs() << "** Deleted " << printID(RegIdx) << "\n");
320 }
321}
322
323void Rematerializer::deleteReg(RegisterIdx RegIdx) {
324 noteRegDeleted(RegIdx);
325
326 Reg &DeleteReg = Regs[RegIdx];
327 assert(DeleteReg.DefMI && "register was already deleted");
328 // It is not possible for the deleted instruction to be the upper region
329 // boundary since we don't ever consider them rematerializable.
330 MachineBasicBlock::iterator &RegionBegin = Regions[DeleteReg.DefRegion].first;
331 if (RegionBegin == DeleteReg.DefMI)
332 RegionBegin = std::next(MachineBasicBlock::iterator(DeleteReg.DefMI));
333 LIS.RemoveMachineInstrFromMaps(*DeleteReg.DefMI);
334 DeleteReg.DefMI->eraseFromParent();
335 DeleteReg.DefMI = nullptr;
336}
337
340 LiveIntervals &LIS)
341 : Regions(Regions), MRI(MF.getRegInfo()), LIS(LIS),
342 TII(*MF.getSubtarget().getInstrInfo()), TRI(TII.getRegisterInfo()) {
343#ifdef EXPENSIVE_CHECKS
344 // Check that regions are valid.
346 for (const auto &[RegionBegin, RegionEnd] : Regions) {
347 assert(RegionBegin != RegionEnd && "empty region");
348 for (auto MI = RegionBegin; MI != RegionEnd; ++MI) {
349 bool IsNewMI = SeenMIs.insert(&*MI).second;
350 assert(IsNewMI && "overlapping regions");
351 assert(!MI->isTerminator() && "terminator in region");
352 }
353 if (RegionEnd != RegionBegin->getParent()->end()) {
354 bool IsNewMI = SeenMIs.insert(&*RegionEnd).second;
355 assert(IsNewMI && "overlapping regions (upper bound)");
356 }
357 }
358#endif
359}
360
362 Regs.clear();
363 UnrematableOprds.clear();
364 Origins.clear();
365 Rematerializations.clear();
366 RegionMBB.clear();
367 RegToIdx.clear();
368 LISUpdates.clear();
369 if (Regions.empty())
370 return false;
371
372 /// Maps all MIs to their parent region. Region terminators are considered
373 /// part of the region they terminate.
375
376 // Initialize MI to containing region mapping.
377 RegionMBB.reserve(Regions.size());
378 for (unsigned I = 0, E = Regions.size(); I < E; ++I) {
379 RegionBoundaries Region = Regions[I];
380 assert(Region.first != Region.second && "empty cannot be region");
381 for (auto MI = Region.first; MI != Region.second; ++MI) {
382 assert(!MIRegion.contains(&*MI) && "regions should not intersect");
383 MIRegion.insert({&*MI, I});
384 }
386 RegionMBB.push_back(&MBB);
387
388 // A terminator instruction is considered part of the region it terminates.
389 if (Region.second != MBB.end()) {
390 MachineInstr *RegionTerm = &*Region.second;
391 assert(!MIRegion.contains(RegionTerm) && "regions should not intersect");
392 MIRegion.insert({RegionTerm, I});
393 }
394 }
395
396 const unsigned NumVirtRegs = MRI.getNumVirtRegs();
397 BitVector SeenRegs(NumVirtRegs);
398 for (unsigned I = 0, E = NumVirtRegs; I != E; ++I) {
399 if (!SeenRegs[I])
400 addRegIfRematerializable(I, MIRegion, SeenRegs);
401 }
402 assert(Regs.size() == UnrematableOprds.size());
403
404 LLVM_DEBUG({
405 for (RegisterIdx I = 0, E = getNumRegs(); I < E; ++I)
406 dbgs() << printDependencyDAG(I) << '\n';
407 });
408 return !Regs.empty();
409}
410
411void Rematerializer::addRegIfRematerializable(
412 unsigned VirtRegIdx, const DenseMap<MachineInstr *, unsigned> &MIRegion,
413 BitVector &SeenRegs) {
414 assert(!SeenRegs[VirtRegIdx] && "register already seen");
415 Register DefReg = Register::index2VirtReg(VirtRegIdx);
416 SeenRegs.set(VirtRegIdx);
417
418 MachineOperand *MO = MRI.getOneDef(DefReg);
419 if (!MO)
420 return;
421 MachineInstr &DefMI = *MO->getParent();
422 if (!isMIRematerializable(DefMI))
423 return;
424 auto DefRegion = MIRegion.find(&DefMI);
425 if (DefRegion == MIRegion.end())
426 return;
427
428 Reg RematReg;
429 RematReg.DefMI = &DefMI;
430 RematReg.DefRegion = DefRegion->second;
431 unsigned SubIdx = DefMI.getOperand(0).getSubReg();
432 RematReg.Mask = SubIdx ? TRI.getSubRegIndexLaneMask(SubIdx)
433 : MRI.getMaxLaneMaskForVReg(DefReg);
434
435 // Collect the candidate's direct users, both rematerializable and
436 // unrematerializable. MIs outside provided regions cannot be tracked so the
437 // registers they use are not safely rematerializable.
438 for (MachineInstr &UseMI : MRI.use_nodbg_instructions(DefReg)) {
439 if (auto UseRegion = MIRegion.find(&UseMI); UseRegion != MIRegion.end())
440 RematReg.addUser(&UseMI, UseRegion->second);
441 else
442 return;
443 }
444 if (RematReg.Uses.empty())
445 return;
446
447 // Collect the candidate's dependencies. If the same register is used
448 // multiple times we just need to consider it once.
450 SmallVector<unsigned, 2> UnrematDeps;
451 for (const auto &[MOIdx, MO] : enumerate(RematReg.DefMI->operands())) {
452 Register DepReg = getRegDependency(MO);
453 if (!DepReg || !AllDepRegs.insert(DepReg).second)
454 continue;
455 unsigned DepRegIdx = DepReg.virtRegIndex();
456 if (!SeenRegs[DepRegIdx])
457 addRegIfRematerializable(DepRegIdx, MIRegion, SeenRegs);
458 if (auto DepIt = RegToIdx.find(DepReg); DepIt != RegToIdx.end())
459 RematReg.Dependencies.push_back(Reg::Dependency(MOIdx, DepIt->second));
460 else
461 UnrematDeps.push_back(MOIdx);
462 }
463
464 // The register is rematerializable.
465 RegToIdx.insert({DefReg, Regs.size()});
466 Regs.push_back(RematReg);
467 UnrematableOprds.push_back(UnrematDeps);
468}
469
470bool Rematerializer::isMIRematerializable(const MachineInstr &MI) const {
471 if (!TII.isReMaterializable(MI))
472 return false;
473
474 assert(MI.getOperand(0).getReg().isVirtual() && "should be virtual");
475 assert(MRI.hasOneDef(MI.getOperand(0).getReg()) && "should have single def");
476
477 for (const MachineOperand &MO : MI.all_uses()) {
478 // We can't remat physreg uses, unless it is a constant or an ignorable
479 // use (e.g. implicit exec use on VALU instructions)
480 if (MO.getReg().isPhysical()) {
481 if (MRI.isConstantPhysReg(MO.getReg()) || TII.isIgnorableUse(MO))
482 continue;
483 return false;
484 }
485 }
486
487 return true;
488}
489
491 if (!MI.getNumOperands() || !MI.getOperand(0).isReg() ||
492 MI.getOperand(0).readsReg())
493 return NoReg;
494 Register Reg = MI.getOperand(0).getReg();
495 auto UserRegIt = RegToIdx.find(Reg);
496 if (UserRegIt == RegToIdx.end())
497 return NoReg;
498 return UserRegIt->second;
499}
500
502 RegisterIdx RegIdx, unsigned UseRegion,
504 SmallVectorImpl<Reg::Dependency> &&Dependencies) {
505 RegisterIdx NewRegIdx = Regs.size();
506
507 Reg &NewReg = Regs.emplace_back();
508 Reg &FromReg = Regs[RegIdx];
509 NewReg.Mask = FromReg.Mask;
510 NewReg.DefRegion = UseRegion;
511 NewReg.Dependencies = std::move(Dependencies);
512
513 // Track rematerialization link between registers. Origins are always
514 // registers that existed originally, and rematerializations are always
515 // attached to them.
516 const RegisterIdx OriginIdx = getOriginOrSelf(RegIdx);
517 Origins.push_back(OriginIdx);
518 Rematerializations[OriginIdx].insert(NewRegIdx);
519
520 // Use the TII to rematerialize the defining instruction with a new defined
521 // register.
522 Register NewDefReg = MRI.cloneVirtualRegister(FromReg.getDefReg());
523 TII.reMaterialize(*RegionMBB[UseRegion], InsertPos, NewDefReg, 0,
524 *FromReg.DefMI);
525 NewReg.DefMI = &*std::prev(InsertPos);
526 RegToIdx.insert({NewDefReg, NewRegIdx});
527 postRematerialization(RegIdx, NewRegIdx, InsertPos);
528
529 noteRegCreated(NewRegIdx);
530 LLVM_DEBUG(dbgs() << "** Rematerialized " << printID(RegIdx) << " as "
531 << printRematReg(NewRegIdx) << '\n');
532 return NewRegIdx;
533}
534
536 RegisterIdx RegIdx, unsigned DefRegion,
537 MachineBasicBlock::iterator InsertPos, Register DefReg,
538 SmallVectorImpl<Reg::Dependency> &&Dependencies) {
539 assert(RegToIdx.contains(DefReg) && "unknown defined register");
540 assert(RegToIdx.at(DefReg) == RegIdx && "incorrect defined register");
541 assert(!getReg(RegIdx).DefMI && "register is still alive");
542
543 Reg &OriginReg = Regs[RegIdx];
544 OriginReg.DefRegion = DefRegion;
545 OriginReg.Dependencies = std::move(Dependencies);
546
547 // Re-establish the link between origin and rematerialization if necessary.
548 const bool RecreateOriginalReg = isOriginalRegister(RegIdx);
549 if (!RecreateOriginalReg)
550 Rematerializations[getOriginOf(RegIdx)].insert(RegIdx);
551
552 // Rematerialize from one of the existing rematerializations or from the
553 // origin. We expect at least one to exist, otherwise it would mean the value
554 // held by the original register is no longer available anywhere in the MF.
555 RegisterIdx ModelRegIdx;
556 if (RecreateOriginalReg) {
557 assert(Rematerializations.contains(RegIdx) && "expected remats");
558 ModelRegIdx = *Rematerializations.at(RegIdx).begin();
559 } else {
560 assert(getReg(getOriginOf(RegIdx)).DefMI && "expected alive origin");
561 ModelRegIdx = getOriginOf(RegIdx);
562 }
563 const MachineInstr &ModelDefMI = *getReg(ModelRegIdx).DefMI;
564
565 TII.reMaterialize(*RegionMBB[DefRegion], InsertPos, DefReg, 0, ModelDefMI);
566 OriginReg.DefMI = &*std::prev(InsertPos);
567 postRematerialization(ModelRegIdx, RegIdx, InsertPos);
568 LLVM_DEBUG(dbgs() << "** Recreated " << printID(RegIdx) << " as "
569 << printRematReg(RegIdx) << '\n');
570}
571
572void Rematerializer::postRematerialization(
573 RegisterIdx ModelRegIdx, RegisterIdx RematRegIdx,
574 MachineBasicBlock::iterator InsertPos) {
575
576 // The start of the new register's region may have changed.
577 Reg &ModelReg = Regs[ModelRegIdx], &RematReg = Regs[RematRegIdx];
578 LIS.InsertMachineInstrInMaps(*RematReg.DefMI);
579 MachineBasicBlock::iterator &RegionBegin = Regions[RematReg.DefRegion].first;
580 if (RegionBegin == std::next(MachineBasicBlock::iterator(RematReg.DefMI)))
581 RegionBegin = RematReg.DefMI;
582
583 // Replace dependencies as needed in the rematerialized MI. All dependencies
584 // of the latter gain a new user.
585 auto ZipedDeps = zip_equal(ModelReg.Dependencies, RematReg.Dependencies);
586 for (const auto &[OldDep, NewDep] : ZipedDeps) {
587 assert(OldDep.MOIdx == NewDep.MOIdx && "operand mismatch");
588 LLVM_DEBUG(dbgs() << " Operand #" << OldDep.MOIdx << ": "
589 << printID(OldDep.RegIdx) << " -> "
590 << printID(NewDep.RegIdx) << '\n');
591
592 Reg &NewDepReg = Regs[NewDep.RegIdx];
593 if (OldDep.RegIdx != NewDep.RegIdx) {
594 Register OldDefReg = ModelReg.DefMI->getOperand(OldDep.MOIdx).getReg();
595 RematReg.DefMI->substituteRegister(OldDefReg, NewDepReg.getDefReg(), 0,
596 TRI);
597 LISUpdates.insert(OldDep.RegIdx);
598 }
599 NewDepReg.addUser(RematReg.DefMI, RematReg.DefRegion);
600 LISUpdates.insert(NewDep.RegIdx);
601 }
602}
603
604std::pair<MachineInstr *, MachineInstr *>
606 const LiveIntervals &LIS) const {
607 auto It = Uses.find(UseRegion);
608 if (It == Uses.end())
609 return {nullptr, nullptr};
610 const RegionUsers &RegionUsers = It->getSecond();
611 assert(!RegionUsers.empty() && "empty userset in region");
612
613 auto User = RegionUsers.begin(), UserEnd = RegionUsers.end();
614 MachineInstr *FirstMI = *User, *LastMI = FirstMI;
615 SlotIndex FirstIndex = LIS.getInstructionIndex(*FirstMI),
616 LastIndex = FirstIndex;
617
618 while (++User != UserEnd) {
619 SlotIndex UserIndex = LIS.getInstructionIndex(**User);
620 if (UserIndex < FirstIndex) {
621 FirstIndex = UserIndex;
622 FirstMI = *User;
623 } else if (UserIndex > LastIndex) {
624 LastIndex = UserIndex;
625 LastMI = *User;
626 }
627 }
628
629 return {FirstMI, LastMI};
630}
631
632void Rematerializer::Reg::addUser(MachineInstr *MI, unsigned Region) {
633 Uses[Region].insert(MI);
634}
635
636void Rematerializer::Reg::addUsers(const RegionUsers &NewUsers,
637 unsigned Region) {
638 Uses[Region].insert_range(NewUsers);
639}
640
641void Rematerializer::Reg::eraseUser(MachineInstr *MI, unsigned Region) {
642 RegionUsers &RUsers = Uses.at(Region);
643 assert(RUsers.contains(MI) && "user not in region");
644 if (RUsers.size() == 1)
645 Uses.erase(Region);
646 else
647 RUsers.erase(MI);
648}
649
651 return Printable([&, RootIdx](raw_ostream &OS) {
653 std::function<void(RegisterIdx, unsigned)> WalkTree =
654 [&](RegisterIdx RegIdx, unsigned Depth) -> void {
655 unsigned MaxDepth = std::max(RegDepths.lookup_or(RegIdx, Depth), Depth);
656 RegDepths.emplace_or_assign(RegIdx, MaxDepth);
657 for (const Reg::Dependency &Dep : getReg(RegIdx).Dependencies)
658 WalkTree(Dep.RegIdx, Depth + 1);
659 };
660 WalkTree(RootIdx, 0);
661
662 // Sort in decreasing depth order to print root at the bottom.
664 RegDepths.end());
665 sort(Regs, [](const auto &LHS, const auto &RHS) {
666 return LHS.second > RHS.second;
667 });
668
669 OS << printID(RootIdx) << " has " << Regs.size() - 1 << " dependencies\n";
670 for (const auto &[RegIdx, Depth] : Regs) {
671 OS << indent(Depth, 2) << (Depth ? '|' : '*') << ' '
672 << printRematReg(RegIdx, /*SkipRegions=*/Depth) << '\n';
673 }
674 OS << printRegUsers(RootIdx);
675 });
676}
677
679 return Printable([&, RegIdx](raw_ostream &OS) {
680 const Reg &PrintReg = getReg(RegIdx);
681 OS << '(' << RegIdx << '/';
682 if (!PrintReg.DefMI) {
683 OS << "<dead>";
684 } else {
685 OS << printReg(PrintReg.getDefReg(), &TRI,
686 PrintReg.DefMI->getOperand(0).getSubReg(), &MRI);
687 }
688 OS << ")[" << PrintReg.DefRegion << "]";
689 });
690}
691
693 bool SkipRegions) const {
694 return Printable([&, RegIdx, SkipRegions](raw_ostream &OS) {
695 const Reg &PrintReg = getReg(RegIdx);
696 if (!SkipRegions) {
697 OS << printID(RegIdx) << " [" << PrintReg.DefRegion;
698 if (!PrintReg.Uses.empty()) {
699 assert(PrintReg.DefMI && "dead register cannot have uses");
700 const LiveInterval &LI = LIS.getInterval(PrintReg.getDefReg());
701 // First display all regions in which the register is live-through and
702 // not used.
703 bool First = true;
704 for (const auto [I, Bounds] : enumerate(Regions)) {
705 if (Bounds.first == Bounds.second)
706 continue;
707 if (!PrintReg.Uses.contains(I) &&
708 LI.liveAt(LIS.getInstructionIndex(*Bounds.first)) &&
709 LI.liveAt(LIS.getInstructionIndex(*std::prev(Bounds.second))
710 .getRegSlot())) {
711 OS << (First ? " - " : ",") << I;
712 First = false;
713 }
714 }
715 OS << (First ? " --> " : " -> ");
716
717 // Then display regions in which the register is used.
718 auto It = PrintReg.Uses.begin();
719 OS << It->first;
720 while (++It != PrintReg.Uses.end())
721 OS << "," << It->first;
722 }
723 OS << "] ";
724 }
725 OS << printID(RegIdx) << ' ';
726 PrintReg.DefMI->print(OS, /*IsStandalone=*/true, /*SkipOpers=*/false,
727 /*SkipDebugLoc=*/false, /*AddNewLine=*/false);
728 OS << " @ ";
729 LIS.getInstructionIndex(*PrintReg.DefMI).print(OS);
730 });
731}
732
734 return Printable([&, RegIdx](raw_ostream &OS) {
735 for (const auto &[UseRegion, Users] : getReg(RegIdx).Uses) {
736 for (MachineInstr *MI : Users)
737 OS << " User " << printUser(MI, UseRegion) << '\n';
738 }
739 });
740}
741
743 std::optional<unsigned> UseRegion) const {
744 return Printable([&, MI, UseRegion](raw_ostream &OS) {
745 RegisterIdx RegIdx = getDefRegIdx(*MI);
746 if (RegIdx != NoReg) {
747 OS << printID(RegIdx);
748 } else {
749 OS << "(-/-)[";
750 if (UseRegion)
751 OS << *UseRegion;
752 else
753 OS << '?';
754 OS << ']';
755 }
756 OS << ' ';
757 MI->print(OS, /*IsStandalone=*/true, /*SkipOpers=*/false,
758 /*SkipDebugLoc=*/false, /*AddNewLine=*/false);
759 OS << " @ ";
760 LIS.getInstructionIndex(*MI).print(OS);
761 });
762}
763
764Rollbacker::RollbackInfo::RollbackInfo(const Rematerializer &Remater,
765 RegisterIdx RegIdx) {
766 const Rematerializer::Reg &Reg = Remater.getReg(RegIdx);
767 DefReg = Reg.getDefReg();
768 DefRegion = Reg.DefRegion;
769 Dependencies = Reg.Dependencies;
770
771 InsertPos = std::next(Reg.DefMI->getIterator());
772 if (InsertPos != Reg.DefMI->getParent()->end())
773 NextRegIdx = Remater.getDefRegIdx(*InsertPos);
774 else
775 NextRegIdx = Rematerializer::NoReg;
776}
777
779 RegisterIdx RegIdx) {
780 if (RollingBack)
781 return;
782 Rematerializations[Remater.getOriginOf(RegIdx)].insert(RegIdx);
783}
784
786 RegisterIdx RegIdx) {
787 if (RollingBack || Remater.isRematerializedRegister(RegIdx))
788 return;
789 DeadRegs.try_emplace(RegIdx, Remater, RegIdx);
790}
791
793 RollingBack = true;
794
795 // Re-create deleted registers.
796 for (auto &[RegIdx, Info] : DeadRegs) {
797 assert(!Remater.getReg(RegIdx).isAlive() && "register should be dead");
798
799 // The MI that was originally just after the MI defining the register we
800 // are trying to re-create may have been deleted. In such cases, we can
801 // re-create at that MI's own insert position (and apply the same logic
802 // recursively).
803 MachineBasicBlock::iterator InsertPos = Info.InsertPos;
804 RegisterIdx NextRegIdx = Info.NextRegIdx;
805 while (NextRegIdx != Rematerializer::NoReg) {
806 const auto *NextRegRollback = DeadRegs.find(NextRegIdx);
807 if (NextRegRollback == DeadRegs.end())
808 break;
809 InsertPos = NextRegRollback->second.InsertPos;
810 NextRegIdx = NextRegRollback->second.NextRegIdx;
811 }
812 Remater.recreateReg(RegIdx, Info.DefRegion, InsertPos, Info.DefReg,
813 std::move(Info.Dependencies));
814 }
815
816 // Rollback rematerializations.
817 for (const auto &[RegIdx, RematsOf] : Rematerializations) {
818 for (RegisterIdx RematRegIdx : RematsOf) {
819 // It is possible that rematerializations were deleted. Their users would
820 // have been transfered to some other rematerialization so we can safely
821 // ignore them. Original registers that were deleted were just re-created
822 // so we do not need to check for that.
823 if (Remater.getReg(RematRegIdx).isAlive())
824 Remater.transferAllUsers(RematRegIdx, RegIdx);
825 }
826 }
827
828 Remater.updateLiveIntervals();
829 DeadRegs.clear();
830 Rematerializations.clear();
831 RollingBack = false;
832}
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
IRTranslator LLVM IR MI
iv Induction Variable Users
Definition IVUsers.cpp:48
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
This file implements a map that provides insertion order iteration.
Promote Memory to Register
Definition Mem2Reg.cpp:110
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 contains some templates that are useful if you are working with the STL at all.
This file implements a set that has insertion order iteration characteristics.
#define LLVM_DEBUG(...)
Definition Debug.h:114
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
BitVector & set()
Definition BitVector.h:370
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:178
std::pair< iterator, bool > emplace_or_assign(const KeyT &Key, Ts &&...Args)
Definition DenseMap.h:315
iterator begin()
Definition DenseMap.h:78
iterator end()
Definition DenseMap.h:81
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:169
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
Definition DenseMap.h:215
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:241
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Definition DenseMap.h:114
Implements a dense probed hash-table based set.
Definition DenseSet.h:279
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&)>.
Definition Printable.h:38
RegionT * getParent() const
Get the parent of the Region.
Definition RegionInfo.h:362
Wrapper class representing virtual and physical registers.
Definition Register.h:20
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
Definition Register.h:72
unsigned virtRegIndex() const
Convert a virtual register number to a 0-based index.
Definition Register.h:87
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
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.
Definition SetVector.h:151
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:66
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.
Definition DenseSet.h:291
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:339
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.
Definition Use.h:35
VNInfo - Value Number Information.
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:202
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#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.
Definition STLExtras.h:841
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
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