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"
26#include "llvm/Support/Debug.h"
27
28#define DEBUG_TYPE "rematerializer"
29
30using namespace llvm;
32
33/// Checks whether the value in \p LI at \p UseIdx is identical to \p OVNI (this
34/// implies it is also live there). When \p LI has sub-ranges, checks that
35/// all sub-ranges intersecting with \p Mask are also live at \p UseIdx.
36static bool isIdenticalAtUse(const VNInfo &OVNI, LaneBitmask Mask,
37 SlotIndex UseIdx, const LiveInterval &LI) {
38 if (&OVNI != LI.getVNInfoAt(UseIdx))
39 return false;
40
41 if (LI.hasSubRanges()) {
42 // Check that intersecting subranges are live at user.
43 for (const LiveInterval::SubRange &SR : LI.subranges()) {
44 if ((SR.LaneMask & Mask).none())
45 continue;
46 if (!SR.liveAt(UseIdx))
47 return false;
48
49 // Early exit if all used lanes are checked. No need to continue.
50 Mask &= ~SR.LaneMask;
51 if (Mask.none())
52 break;
53 }
54 }
55 return true;
56}
57
58/// If \p MO is a virtual read register, returns it. Otherwise returns the
59/// sentinel register.
61 if (!MO.isReg() || !MO.readsReg())
62 return Register();
63 Register Reg = MO.getReg();
64 if (Reg.isPhysical()) {
65 // By the requirements on trivially rematerializable instructions, a
66 // physical register use is either constant or ignorable.
67 return Register();
68 }
69 return Reg;
70}
71
73 unsigned UseRegion,
75 MachineInstr *FirstMI =
76 getReg(RootIdx).getRegionUseBounds(UseRegion, LIS).first;
77 RegisterIdx NewRegIdx = rematerializeToPos(RootIdx, FirstMI, DRI);
78 transferRegionUsers(RootIdx, NewRegIdx, UseRegion);
79 return NewRegIdx;
80}
81
86 assert(!DRI.DependencyMap.contains(RootIdx));
87 LLVM_DEBUG(dbgs() << "Rematerializing " << printID(RootIdx) << " to "
88 << printUser(&*InsertPos) << '\n');
89
90 // Traverse the root's dependency DAG depth-first to find the set of
91 // registers we must rematerialize along with it and a legal order to
92 // rematerialize them in.
93 SmallVector<RegisterIdx, 4> DepDAG{RootIdx};
95 RematOrder.insert(RootIdx);
96 do {
97 RegisterIdx RegIdx = DepDAG.pop_back_val();
98 for (const Reg::Dependency &Dep : getReg(RegIdx).Dependencies) {
99 // The dependency may already have a rematerialization ready to use.
100 if (DRI.DependencyMap.contains(Dep.RegIdx))
101 continue;
102 // We may have already seen the dependency in the dependency DAG.
103 if (RematOrder.contains(Dep.RegIdx))
104 continue;
105 DepDAG.push_back(Dep.RegIdx);
106 RematOrder.insert(Dep.RegIdx);
107 }
108 } while (!DepDAG.empty());
109
110 // Rematerialize all necessary registers in the root's dependency DAG. At each
111 // rematerialization, dependencies should already be available.
112 RegisterIdx LastNewIdx;
113 for (RegisterIdx RegIdx : reverse(RematOrder)) {
114 assert(!DRI.DependencyMap.contains(RegIdx) && "useless remat");
116 for (const Reg::Dependency &Dep : getReg(RegIdx).Dependencies)
117 Dependencies.emplace_back(Dep.MOIdx, DRI.DependencyMap.at(Dep.RegIdx));
118 LastNewIdx = rematerializeReg(RegIdx, InsertPos, std::move(Dependencies));
119 DRI.DependencyMap.insert({RegIdx, LastNewIdx});
120 }
121
122 return LastNewIdx;
123}
124
126 auto Remats = Rematerializations.find(RootIdx);
127 if (Remats == Rematerializations.end())
128 return;
129
130 LLVM_DEBUG(dbgs() << "Rolling back rematerializations of " << printID(RootIdx)
131 << '\n');
132
133 reviveRegIfDead(RootIdx);
134 // All of the rematerialization's users must use the revived register.
135 for (RegisterIdx RematRegIdx : Remats->getSecond()) {
136 for (const auto &[UseRegion, RegionUsers] : Regs[RematRegIdx].Uses)
137 transferRegionUsers(RematRegIdx, RootIdx, UseRegion);
138 }
139 Rematerializations.erase(RootIdx);
140
141 LLVM_DEBUG(dbgs() << "** Rolled back rematerializations of "
142 << printID(RootIdx) << '\n');
143}
144
146 assert(getReg(RematIdx).DefMI && !Revivable.contains(RematIdx) &&
147 "cannot rollback dead register");
148 const RegisterIdx OriginRegIdx = getOriginOf(RematIdx);
149 reviveRegIfDead(OriginRegIdx);
150 for (const auto &[UseRegion, RegionUsers] : Regs[RematIdx].Uses)
151 transferRegionUsers(RematIdx, OriginRegIdx, UseRegion);
152}
153
155 if (getReg(RootIdx).isAlive())
156 return;
157 assert(Revivable.contains(RootIdx) && "not revivable");
158
159 // Traverse the root's dependency DAG depth-first to find the set of
160 // registers we must revive and a legal order to revive them in.
161 SmallVector<RegisterIdx, 4> DepDAG{RootIdx};
163 ReviveOrder.insert(RootIdx);
164 do {
165 // All dependencies of a revived register need to be alive too.
166 const Reg &ReviveReg = getReg(DepDAG.pop_back_val());
167 for (const Reg::Dependency &Dep : ReviveReg.Dependencies) {
168 // We may have already seen the dependency in the dependency DAG.
169 if (ReviveOrder.contains(Dep.RegIdx))
170 continue;
171
172 // Dead dependencies need to be revived.
173 Reg &DepReg = Regs[Dep.RegIdx];
174 if (!DepReg.isAlive()) {
175 assert(Revivable.contains(Dep.RegIdx) && "not revivable");
176 ReviveOrder.insert(Dep.RegIdx);
177 DepDAG.push_back(Dep.RegIdx);
178 }
179
180 // All dependencies get a new user (the revived register).
181 DepReg.addUser(ReviveReg.DefMI, ReviveReg.DefRegion);
182 LISUpdates.insert(Dep.RegIdx);
183 }
184 } while (!DepDAG.empty());
185
186 for (RegisterIdx RegIdx : reverse(ReviveOrder)) {
187 // Pick any rematerialization to retrieve the original opcode from.
188 Reg &ReviveReg = Regs[RegIdx];
189 assert(Rematerializations.contains(RegIdx) && "no remats");
190 RegisterIdx RematIdx = *Rematerializations.at(RegIdx).begin();
191 ReviveReg.DefMI->setDesc(getReg(RematIdx).DefMI->getDesc());
192 for (const auto &[MOIdx, Reg] : Revivable.at(RegIdx))
193 ReviveReg.DefMI->getOperand(MOIdx).setReg(Reg);
194 Revivable.erase(RegIdx);
195 LISUpdates.insert(RegIdx);
196
197 LLVM_DEBUG({
198 dbgs() << "** Revived " << printID(RegIdx) << " @ ";
199 LIS.getInstructionIndex(*ReviveReg.DefMI).print(dbgs());
200 dbgs() << '\n';
201 });
202 }
203}
204
206 MachineInstr &UserMI) {
207 transferUserImpl(FromRegIdx, ToRegIdx, UserMI);
208 unsigned UserRegion = MIRegion.at(&UserMI);
209 Regs[FromRegIdx].eraseUser(&UserMI, UserRegion);
210 Regs[ToRegIdx].addUser(&UserMI, UserRegion);
211 deleteRegIfUnused(FromRegIdx);
212}
213
215 RegisterIdx ToRegIdx,
216 unsigned UseRegion) {
217 auto &FromRegUsers = Regs[FromRegIdx].Uses;
218 auto UsesIt = FromRegUsers.find(UseRegion);
219 if (UsesIt == FromRegUsers.end())
220 return;
221
222 const SmallDenseSet<MachineInstr *, 4> &RegionUsers = UsesIt->getSecond();
223 for (MachineInstr *UserMI : RegionUsers)
224 transferUserImpl(FromRegIdx, ToRegIdx, *UserMI);
225 Regs[ToRegIdx].addUsers(RegionUsers, UseRegion);
226 FromRegUsers.erase(UseRegion);
227 deleteRegIfUnused(FromRegIdx);
228}
229
230void Rematerializer::transferUserImpl(RegisterIdx FromRegIdx,
231 RegisterIdx ToRegIdx,
232 MachineInstr &UserMI) {
233 assert(MIRegion.contains(&UserMI) && "unknown user");
234 assert(getReg(FromRegIdx).Uses.at(MIRegion.at(&UserMI)).contains(&UserMI) &&
235 "not a user");
236 assert(FromRegIdx != ToRegIdx && "identical registers");
237 assert(getOriginOrSelf(FromRegIdx) == getOriginOrSelf(ToRegIdx) &&
238 "unrelated registers");
239
240 LLVM_DEBUG(dbgs() << "User transfer from " << printID(FromRegIdx) << " to "
241 << printID(ToRegIdx) << ": " << printUser(&UserMI) << '\n');
242
243 UserMI.substituteRegister(getReg(FromRegIdx).getDefReg(),
244 getReg(ToRegIdx).getDefReg(), 0, TRI);
245 LISUpdates.insert(FromRegIdx);
246 LISUpdates.insert(ToRegIdx);
247
248 // If the user is rematerializable, we must change its dependency to the
249 // new register.
250 if (RegisterIdx UserRegIdx = getDefRegIdx(UserMI); UserRegIdx != NoReg) {
251 // Look for the user's dependency that matches the register.
252 for (Reg::Dependency &Dep : Regs[UserRegIdx].Dependencies) {
253 if (Dep.RegIdx == FromRegIdx) {
254 Dep.RegIdx = ToRegIdx;
255 return;
256 }
257 }
258 llvm_unreachable("broken dependency");
259 }
260}
261
263 DenseSet<Register> SeenUnrematRegs;
264 for (RegisterIdx RegIdx : LISUpdates) {
265 const Reg &UpdateReg = getReg(RegIdx);
266 assert((UpdateReg.DefMI || Revivable.contains(RegIdx)) && "dead reg");
267
268 Register DefReg = UpdateReg.getDefReg();
269 if (LIS.hasInterval(DefReg))
270 LIS.removeInterval(DefReg);
271 LIS.createAndComputeVirtRegInterval(DefReg);
272
273 LLVM_DEBUG({
274 dbgs() << "Re-computed interval for " << printID(RegIdx) << ": ";
275 LIS.getInterval(DefReg).print(dbgs());
276 dbgs() << '\n' << printRegUsers(RegIdx);
277 });
278
279 // Update intervals for unrematerializable operands.
280 for (unsigned MOIdx : getUnrematableOprds(RegIdx)) {
281 Register UnrematReg = UpdateReg.DefMI->getOperand(MOIdx).getReg();
282 if (!SeenUnrematRegs.insert(UnrematReg).second)
283 continue;
284 LIS.removeInterval(UnrematReg);
285 LIS.createAndComputeVirtRegInterval(UnrematReg);
287 dbgs() << " Re-computed interval for register "
288 << printReg(UnrematReg, &TRI,
289 UpdateReg.DefMI->getOperand(MOIdx).getSubReg(),
290 &MRI)
291 << '\n');
292 }
293 }
294 LISUpdates.clear();
295}
296
298 for (auto &[RegIdx, _] : Revivable)
299 deleteReg(RegIdx);
300 Revivable.clear();
301}
302
305 if (Uses.empty())
306 return true;
307 Register Reg = MO.getReg();
308 unsigned SubIdx = MO.getSubReg();
309 LaneBitmask Mask = SubIdx ? TRI.getSubRegIndexLaneMask(SubIdx)
310 : MRI.getMaxLaneMaskForVReg(Reg);
311 const LiveInterval &LI = LIS.getInterval(Reg);
312 const VNInfo *DefVN =
313 LI.getVNInfoAt(LIS.getInstructionIndex(*MO.getParent()).getRegSlot(true));
314 for (SlotIndex Use : Uses) {
315 if (!isIdenticalAtUse(*DefVN, Mask, Use, LI))
316 return false;
317 }
318 return true;
319}
320
322 unsigned Region,
323 SlotIndex Before) const {
324 auto It = Rematerializations.find(getOriginOrSelf(RegIdx));
325 if (It == Rematerializations.end())
326 return NoReg;
327 const RematsOf &Remats = It->getSecond();
328
329 SlotIndex BestSlot;
330 RegisterIdx BestRegIdx = NoReg;
331 for (RegisterIdx RematRegIdx : Remats) {
332 const Reg &RematReg = getReg(RematRegIdx);
333 if (RematReg.DefRegion != Region || RematReg.Uses.empty())
334 continue;
335 SlotIndex RematRegSlot =
336 LIS.getInstructionIndex(*RematReg.DefMI).getRegSlot();
337 if (RematRegSlot < Before &&
338 (BestRegIdx == NoReg || RematRegSlot > BestSlot)) {
339 BestSlot = RematRegSlot;
340 BestRegIdx = RematRegIdx;
341 }
342 }
343 return BestRegIdx;
344}
345
346void Rematerializer::deleteRegIfUnused(RegisterIdx RootIdx) {
347 if (!getReg(RootIdx).Uses.empty())
348 return;
349
350 // Traverse the root's dependency DAG depth-first to find the set of registers
351 // we can delete and a legal order to delete them in.
352 SmallVector<RegisterIdx, 4> DepDAG{RootIdx};
354 DeleteOrder.insert(RootIdx);
355 do {
356 // A deleted register's dependencies may be deletable too.
357 const Reg &DeleteReg = getReg(DepDAG.pop_back_val());
358 for (const Reg::Dependency &Dep : DeleteReg.Dependencies) {
359 // All dependencies loose a user (the delete register).
360 Reg &DepReg = Regs[Dep.RegIdx];
361 DepReg.eraseUser(DeleteReg.DefMI, DeleteReg.DefRegion);
362 if (DepReg.Uses.empty()) {
363 DeleteOrder.insert(Dep.RegIdx);
364 DepDAG.push_back(Dep.RegIdx);
365 }
366 }
367 } while (!DepDAG.empty());
368
369 for (RegisterIdx RegIdx : reverse(DeleteOrder)) {
370 Reg &DeleteReg = Regs[RegIdx];
371 LIS.removeInterval(DeleteReg.getDefReg());
372 LISUpdates.erase(RegIdx);
373 const bool IsRematerializedReg = isRematerializedRegister(RegIdx);
374 if (SupportRollback && !IsRematerializedReg) {
375 // Replace all read registers with the null one to prevent them from
376 // showing up in use-lists, which is disallowed for debug instructions in
377 // live interval calculations. Store mappings between operand indices and
378 // original registers for potential rollback.
379 DenseMap<unsigned, Register> &RegMap =
380 Revivable.try_emplace(RegIdx).first->getSecond();
381 for (auto [Idx, MO] : enumerate(DeleteReg.DefMI->operands())) {
382 if (MO.isReg() && MO.readsReg()) {
383 RegMap.insert({Idx, MO.getReg()});
384 MO.setReg(Register());
385 }
386 }
387 DeleteReg.DefMI->setDesc(TII.get(TargetOpcode::DBG_VALUE));
388 } else {
389 deleteReg(RegIdx);
390 }
391 if (IsRematerializedReg) {
392 // Delete rematerialized register from its origin's rematerializations.
393 RematsOf &OriginRemats = Rematerializations.at(getOriginOf(RegIdx));
394 assert(OriginRemats.contains(RegIdx) && "broken remat<->origin link");
395 OriginRemats.erase(RegIdx);
396 if (OriginRemats.empty())
397 Rematerializations.erase(RegIdx);
398 }
399 LLVM_DEBUG(dbgs() << "** Deleted " << printID(RegIdx) << "\n");
400 }
401}
402
403void Rematerializer::deleteReg(RegisterIdx RegIdx) {
404 Reg &DeleteReg = Regs[RegIdx];
405 assert(DeleteReg.DefMI && "register was already deleted");
406 // It is not possible for the deleted instruction to be the upper region
407 // boundary since we don't ever consider them rematerializable.
408 MachineBasicBlock::iterator &RegionBegin = Regions[DeleteReg.DefRegion].first;
409 if (RegionBegin == DeleteReg.DefMI)
410 RegionBegin = std::next(MachineBasicBlock::iterator(DeleteReg.DefMI));
411 LIS.RemoveMachineInstrFromMaps(*DeleteReg.DefMI);
412 DeleteReg.DefMI->eraseFromParent();
413 MIRegion.erase(DeleteReg.DefMI);
414 DeleteReg.DefMI = nullptr;
415}
416
419 LiveIntervals &LIS)
420 : Regions(Regions), MRI(MF.getRegInfo()), LIS(LIS),
421 TII(*MF.getSubtarget().getInstrInfo()), TRI(TII.getRegisterInfo()) {
422#ifdef EXPENSIVE_CHECKS
423 // Check that regions are valid.
425 for (const auto &[RegionBegin, RegionEnd] : Regions) {
426 assert(RegionBegin != RegionEnd && "empty region");
427 for (auto MI = RegionBegin; MI != RegionEnd; ++MI) {
428 bool IsNewMI = SeenMIs.insert(&*MI).second;
429 assert(IsNewMI && "overlapping regions");
430 assert(!MI->isTerminator() && "terminator in region");
431 }
432 if (RegionEnd != RegionBegin->getParent()->end()) {
433 bool IsNewMI = SeenMIs.insert(&*RegionEnd).second;
434 assert(IsNewMI && "overlapping regions (upper bound)");
435 }
436 }
437#endif
438}
439
440bool Rematerializer::analyze(bool SupportRollback) {
441 Regs.clear();
442 UnrematableOprds.clear();
443 Origins.clear();
444 Rematerializations.clear();
445 MIRegion.clear();
446 RegToIdx.clear();
447 LISUpdates.clear();
448 Revivable.clear();
449 this->SupportRollback = SupportRollback;
450 if (Regions.empty())
451 return false;
452
453 // Initialize MI to containing region mapping.
454 for (unsigned I = 0, E = Regions.size(); I < E; ++I) {
455 RegionBoundaries Region = Regions[I];
456 assert(Region.first != Region.second && "empty cannot be region");
457 for (auto MI = Region.first; MI != Region.second; ++MI) {
458 assert(!MIRegion.contains(&*MI) && "regions should not intersect");
459 MIRegion.insert({&*MI, I});
460 }
461
462 // A terminator instruction is considered part of the region it terminates.
463 if (Region.second != Region.first->getParent()->end()) {
464 MachineInstr *RegionTerm = &*Region.second;
465 assert(!MIRegion.contains(RegionTerm) && "regions should not intersect");
466 MIRegion.insert({RegionTerm, I});
467 }
468 }
469
470 const unsigned NumVirtRegs = MRI.getNumVirtRegs();
471 BitVector SeenRegs(NumVirtRegs);
472 for (unsigned I = 0, E = NumVirtRegs; I != E; ++I) {
473 if (!SeenRegs[I])
474 addRegIfRematerializable(I, SeenRegs);
475 }
476 assert(Regs.size() == UnrematableOprds.size());
477
478 LLVM_DEBUG({
479 for (RegisterIdx I = 0, E = getNumRegs(); I < E; ++I)
480 dbgs() << printDependencyDAG(I) << '\n';
481 });
482 return !Regs.empty();
483}
484
485void Rematerializer::addRegIfRematerializable(unsigned VirtRegIdx,
486 BitVector &SeenRegs) {
487 assert(!SeenRegs[VirtRegIdx] && "register already seen");
488 Register DefReg = Register::index2VirtReg(VirtRegIdx);
489 SeenRegs.set(VirtRegIdx);
490
491 MachineOperand *MO = MRI.getOneDef(DefReg);
492 if (!MO)
493 return;
494 MachineInstr &DefMI = *MO->getParent();
495 if (!isMIRematerializable(DefMI))
496 return;
497 auto DefRegion = MIRegion.find(&DefMI);
498 if (DefRegion == MIRegion.end())
499 return;
500
501 Reg RematReg;
502 RematReg.DefMI = &DefMI;
503 RematReg.DefRegion = DefRegion->second;
504 unsigned SubIdx = DefMI.getOperand(0).getSubReg();
505 RematReg.Mask = SubIdx ? TRI.getSubRegIndexLaneMask(SubIdx)
506 : MRI.getMaxLaneMaskForVReg(DefReg);
507
508 // Collect the candidate's direct users, both rematerializable and
509 // unrematerializable. MIs outside provided regions cannot be tracked so the
510 // registers they use are not safely rematerializable.
511 for (MachineInstr &UseMI : MRI.use_nodbg_instructions(DefReg)) {
512 if (auto UseRegion = MIRegion.find(&UseMI); UseRegion != MIRegion.end())
513 RematReg.addUser(&UseMI, UseRegion->second);
514 else
515 return;
516 }
517 if (RematReg.Uses.empty())
518 return;
519
520 // Collect the candidate's dependencies. If the same register is used
521 // multiple times we just need to consider it once.
523 SmallVector<unsigned, 2> UnrematDeps;
524 for (const auto &[MOIdx, MO] : enumerate(RematReg.DefMI->operands())) {
525 Register DepReg = getRegDependency(MO);
526 if (!DepReg || !AllDepRegs.insert(DepReg).second)
527 continue;
528 unsigned DepRegIdx = DepReg.virtRegIndex();
529 if (!SeenRegs[DepRegIdx])
530 addRegIfRematerializable(DepRegIdx, SeenRegs);
531 if (auto DepIt = RegToIdx.find(DepReg); DepIt != RegToIdx.end())
532 RematReg.Dependencies.push_back(Reg::Dependency(MOIdx, DepIt->second));
533 else
534 UnrematDeps.push_back(MOIdx);
535 }
536
537 // The register is rematerializable.
538 RegToIdx.insert({DefReg, Regs.size()});
539 Regs.push_back(RematReg);
540 UnrematableOprds.push_back(UnrematDeps);
541}
542
543bool Rematerializer::isMIRematerializable(const MachineInstr &MI) const {
544 if (!TII.isReMaterializable(MI))
545 return false;
546
547 assert(MI.getOperand(0).getReg().isVirtual() && "should be virtual");
548 assert(MRI.hasOneDef(MI.getOperand(0).getReg()) && "should have single def");
549
550 for (const MachineOperand &MO : MI.all_uses()) {
551 // We can't remat physreg uses, unless it is a constant or an ignorable
552 // use (e.g. implicit exec use on VALU instructions)
553 if (MO.getReg().isPhysical()) {
554 if (MRI.isConstantPhysReg(MO.getReg()) || TII.isIgnorableUse(MO))
555 continue;
556 return false;
557 }
558 }
559
560 return true;
561}
562
563RegisterIdx Rematerializer::getDefRegIdx(const MachineInstr &MI) const {
564 if (!MI.getNumOperands() || !MI.getOperand(0).isReg() ||
565 MI.getOperand(0).readsReg())
566 return NoReg;
567 Register Reg = MI.getOperand(0).getReg();
568 auto UserRegIt = RegToIdx.find(Reg);
569 if (UserRegIt == RegToIdx.end())
570 return NoReg;
571 return UserRegIt->second;
572}
573
574RegisterIdx Rematerializer::rematerializeReg(
576 SmallVectorImpl<Reg::Dependency> &&Dependencies) {
577 unsigned UseRegion = MIRegion.at(&*InsertPos);
578 RegisterIdx NewRegIdx = Regs.size();
579
580 Reg &NewReg = Regs.emplace_back();
581 Reg &FromReg = Regs[RegIdx];
582 NewReg.Mask = FromReg.Mask;
583 NewReg.DefRegion = UseRegion;
584 NewReg.Dependencies = std::move(Dependencies);
585
586 // Track rematerialization link between registers. Origins are always
587 // registers that existed originally, and rematerializations are always
588 // attached to them.
589 RegisterIdx OriginIdx =
590 isRematerializedRegister(RegIdx) ? getOriginOf(RegIdx) : RegIdx;
591 Origins.push_back(OriginIdx);
592 Rematerializations[OriginIdx].insert(NewRegIdx);
593
594 // Use the TII to rematerialize the defining instruction with a new defined
595 // register.
596 Register NewDefReg = MRI.cloneVirtualRegister(FromReg.getDefReg());
597 TII.reMaterialize(*InsertPos->getParent(), InsertPos, NewDefReg, 0,
598 *FromReg.DefMI);
599 NewReg.DefMI = &*std::prev(InsertPos);
600 RegToIdx.insert({NewDefReg, NewRegIdx});
601
602 // Update the DAG.
603 RegionBoundaries &Bounds = Regions[UseRegion];
604 if (Bounds.first == std::next(MachineBasicBlock::iterator(NewReg.DefMI)))
605 Bounds.first = NewReg.DefMI;
606 LIS.InsertMachineInstrInMaps(*NewReg.DefMI);
607 MIRegion.emplace_or_assign(NewReg.DefMI, UseRegion);
608 LISUpdates.insert(NewRegIdx);
609
610 // Replace dependencies as needed in the rematerialized MI. All dependencies
611 // of the latter gain a new user.
612 auto ZipedDeps = zip_equal(FromReg.Dependencies, NewReg.Dependencies);
613 for (const auto &[OldDep, NewDep] : ZipedDeps) {
614 assert(OldDep.MOIdx == NewDep.MOIdx && "operand mismatch");
615 LLVM_DEBUG(dbgs() << " Operand #" << OldDep.MOIdx << ": "
616 << printID(OldDep.RegIdx) << " -> "
617 << printID(NewDep.RegIdx) << '\n');
618
619 Reg &NewDepReg = Regs[NewDep.RegIdx];
620 if (OldDep.RegIdx != NewDep.RegIdx) {
621 Register OldDefReg = FromReg.DefMI->getOperand(OldDep.MOIdx).getReg();
622 NewReg.DefMI->substituteRegister(OldDefReg, NewDepReg.getDefReg(), 0,
623 TRI);
624 LISUpdates.insert(OldDep.RegIdx);
625 }
626 NewDepReg.addUser(NewReg.DefMI, UseRegion);
627 LISUpdates.insert(NewDep.RegIdx);
628 }
629
630 LLVM_DEBUG({
631 dbgs() << "** Rematerialized " << printID(RegIdx) << " as "
632 << printRematReg(NewRegIdx) << '\n';
633 });
634 return NewRegIdx;
635}
636
637std::pair<MachineInstr *, MachineInstr *>
639 const LiveIntervals &LIS) const {
640 auto It = Uses.find(UseRegion);
641 if (It == Uses.end())
642 return {nullptr, nullptr};
643 const RegionUsers &RegionUsers = It->getSecond();
644 assert(!RegionUsers.empty() && "empty userset in region");
645
646 auto User = RegionUsers.begin(), UserEnd = RegionUsers.end();
647 MachineInstr *FirstMI = *User, *LastMI = FirstMI;
648 SlotIndex FirstIndex = LIS.getInstructionIndex(*FirstMI),
649 LastIndex = FirstIndex;
650
651 while (++User != UserEnd) {
652 SlotIndex UserIndex = LIS.getInstructionIndex(**User);
653 if (UserIndex < FirstIndex) {
654 FirstIndex = UserIndex;
655 FirstMI = *User;
656 } else if (UserIndex > LastIndex) {
657 LastIndex = UserIndex;
658 LastMI = *User;
659 }
660 }
661
662 return {FirstMI, LastMI};
663}
664
665void Rematerializer::Reg::addUser(MachineInstr *MI, unsigned Region) {
666 Uses[Region].insert(MI);
667}
668
669void Rematerializer::Reg::addUsers(const RegionUsers &NewUsers,
670 unsigned Region) {
671 Uses[Region].insert_range(NewUsers);
672}
673
674void Rematerializer::Reg::eraseUser(MachineInstr *MI, unsigned Region) {
675 assert(Uses.contains(Region) && "no user in region");
676 assert(Uses.at(Region).contains(MI) && "user not in region");
677 RegionUsers &RUsers = Uses[Region];
678 if (RUsers.size() == 1)
679 Uses.erase(Region);
680 else
681 RUsers.erase(MI);
682}
683
685 return Printable([&, RootIdx](raw_ostream &OS) {
687 std::function<void(RegisterIdx, unsigned)> WalkTree =
688 [&](RegisterIdx RegIdx, unsigned Depth) -> void {
689 unsigned MaxDepth = std::max(RegDepths.lookup_or(RegIdx, Depth), Depth);
690 RegDepths.emplace_or_assign(RegIdx, MaxDepth);
691 for (const Reg::Dependency &Dep : getReg(RegIdx).Dependencies)
692 WalkTree(Dep.RegIdx, Depth + 1);
693 };
694 WalkTree(RootIdx, 0);
695
696 // Sort in decreasing depth order to print root at the bottom.
698 RegDepths.end());
699 sort(Regs, [](const auto &LHS, const auto &RHS) {
700 return LHS.second > RHS.second;
701 });
702
703 OS << printID(RootIdx) << " has " << Regs.size() - 1 << " dependencies\n";
704 for (const auto &[RegIdx, Depth] : Regs) {
705 OS << indent(Depth, 2) << (Depth ? '|' : '*') << ' '
706 << printRematReg(RegIdx, /*SkipRegions=*/Depth) << '\n';
707 }
708 OS << printRegUsers(RootIdx);
709 });
710}
711
713 return Printable([&, RegIdx](raw_ostream &OS) {
714 const Reg &PrintReg = getReg(RegIdx);
715 OS << '(' << RegIdx << '/';
716 if (!PrintReg.DefMI) {
717 OS << "<dead>";
718 } else {
719 OS << printReg(PrintReg.getDefReg(), &TRI,
720 PrintReg.DefMI->getOperand(0).getSubReg(), &MRI);
721 }
722 OS << ")[" << PrintReg.DefRegion << "]";
723 });
724}
725
727 bool SkipRegions) const {
728 return Printable([&, RegIdx, SkipRegions](raw_ostream &OS) {
729 const Reg &PrintReg = getReg(RegIdx);
730 if (!SkipRegions) {
731 OS << printID(RegIdx) << " [" << PrintReg.DefRegion;
732 if (!PrintReg.Uses.empty()) {
733 assert(PrintReg.DefMI && "dead register cannot have uses");
734 const LiveInterval &LI = LIS.getInterval(PrintReg.getDefReg());
735 // First display all regions in which the register is live-through and
736 // not used.
737 bool First = true;
738 for (const auto [I, Bounds] : enumerate(Regions)) {
739 if (Bounds.first == Bounds.second)
740 continue;
741 if (!PrintReg.Uses.contains(I) &&
742 LI.liveAt(LIS.getInstructionIndex(*Bounds.first)) &&
743 LI.liveAt(LIS.getInstructionIndex(*std::prev(Bounds.second))
744 .getRegSlot())) {
745 OS << (First ? " - " : ",") << I;
746 First = false;
747 }
748 }
749 OS << (First ? " --> " : " -> ");
750
751 // Then display regions in which the register is used.
752 auto It = PrintReg.Uses.begin();
753 OS << It->first;
754 while (++It != PrintReg.Uses.end())
755 OS << "," << It->first;
756 }
757 OS << "] ";
758 }
759 OS << printID(RegIdx) << ' ';
760 PrintReg.DefMI->print(OS, /*IsStandalone=*/true, /*SkipOpers=*/false,
761 /*SkipDebugLoc=*/false, /*AddNewLine=*/false);
762 OS << " @ ";
763 LIS.getInstructionIndex(*PrintReg.DefMI).print(OS);
764 });
765}
766
768 return Printable([&, RegIdx](raw_ostream &OS) {
769 for (const auto &[_, Users] : getReg(RegIdx).Uses) {
770 for (MachineInstr *MI : Users)
771 dbgs() << " User " << printUser(MI) << '\n';
772 }
773 });
774}
775
777 return Printable([&, MI](raw_ostream &OS) {
778 RegisterIdx RegIdx = getDefRegIdx(*MI);
779 if (RegIdx != NoReg)
780 OS << printID(RegIdx);
781 else
782 OS << "(-/-)[" << MIRegion.at(MI) << ']';
783 OS << ' ';
784 MI->print(OS, /*IsStandalone=*/true, /*SkipOpers=*/false,
785 /*SkipDebugLoc=*/false, /*AddNewLine=*/false);
786 OS << " @ ";
787 LIS.getInstructionIndex(*MI).print(dbgs());
788 });
789}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define _
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
ValueT & at(const_arg_type_t< KeyT > Val)
at - Return the entry for the specified key, or abort if no such entry exists.
Definition DenseMap.h:224
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
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()
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 setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
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.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
Register getReg() const
getReg - Returns the register number.
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
Printable printDependencyDAG(RegisterIdx RootIdx) const
RegisterIdx getOriginOrSelf(RegisterIdx RegIdx) const
If RegIdx is a rematerialization, returns its origin's index.
static constexpr unsigned NoReg
Error value for register indices.
Printable printID(RegisterIdx RegIdx) const
void rollbackRematsOf(RegisterIdx RootIdx)
Rolls back all rematerializations of original register RootIdx, transfering all their users back to i...
unsigned getNumRegs() const
RegisterIdx rematerializeToPos(RegisterIdx RootIdx, MachineBasicBlock::iterator InsertPos, DependencyReuseInfo &DRI)
Rematerializes register RootIdx before position InsertPos and returns the new register's index.
void transferUser(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx, MachineInstr &UserMI)
Transfers user UserMI from register FromRegIdx to ToRegIdx, the latter of which must be a remateriali...
RegisterIdx getOriginOf(RegisterIdx RematRegIdx) const
Returns the origin index of rematerializable register RegIdx.
const Reg & getReg(RegisterIdx RegIdx) const
void updateLiveIntervals()
Recomputes all live intervals that have changed as a result of previous rematerializations/rollbacks.
RegisterIdx rematerializeToRegion(RegisterIdx RootIdx, unsigned UseRegion, DependencyReuseInfo &DRI)
Rematerializes register RootIdx just before its first user inside region UseRegion,...
std::pair< MachineBasicBlock::iterator, MachineBasicBlock::iterator > RegionBoundaries
A region's boundaries i.e.
bool analyze(bool SupportRollback)
Goes through the whole MF and identifies all rematerializable registers.
void rollback(RegisterIdx RematIdx)
Rolls back register RematIdx (which must be a rematerialization) transfering all its users back to it...
unsigned RegisterIdx
Index type for rematerializable registers.
void reviveRegIfDead(RegisterIdx RootIdx)
Revives original register RootIdx at its original position in the MIR if it was fully rematerialized ...
bool isMOIdenticalAtUses(MachineOperand &MO, ArrayRef< SlotIndex > Uses) const
Determines whether (sub-)register operand MO has the same value at all Uses as at MO.
void transferRegionUsers(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx, unsigned UseRegion)
Transfers all users of register FromRegIdx in region UseRegion to ToRegIdx, the latter of which must ...
void commitRematerializations()
Deletes unused rematerialized registers that were left in the MIR to support rollback.
Rematerializer(MachineFunction &MF, SmallVectorImpl< RegionBoundaries > &Regions, LiveIntervals &LIS)
Simply initializes some internal state, does not identify rematerialization candidates.
ArrayRef< unsigned > getUnrematableOprds(unsigned RegIdx) const
Returns operand indices corresponding to unrematerializable operands for any register RegIdx.
Printable printUser(const MachineInstr *MI) const
bool isRematerializedRegister(RegisterIdx RegIdx) const
Whether register RegIdx is a rematerialization of some original register.
Printable printRematReg(RegisterIdx RegIdx, bool SkipRegions=false) const
Printable printRegUsers(RegisterIdx RegIdx) const
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 contains(const_arg_type key) const
Check if the SetVector contains the given key.
Definition SetVector.h:252
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.
Definition Types.h:26
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).
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.
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