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 const RegisterIdx OriginIdx = getOriginOf(RegIdx);
314 RematsOf &OriginRemats = Rematerializations.at(OriginIdx);
315 assert(OriginRemats.contains(RegIdx) && "broken remat<->origin link");
316 OriginRemats.erase(RegIdx);
317 if (OriginRemats.empty())
318 Rematerializations.erase(OriginIdx);
319 }
320 LLVM_DEBUG(dbgs() << "** Deleted " << printID(RegIdx) << "\n");
321 }
322}
323
324void Rematerializer::deleteReg(RegisterIdx RegIdx) {
325 noteRegDeleted(RegIdx);
326
327 Reg &DeleteReg = Regs[RegIdx];
328 assert(DeleteReg.DefMI && "register was already deleted");
329 // It is not possible for the deleted instruction to be the upper region
330 // boundary since we don't ever consider them rematerializable.
331 MachineBasicBlock::iterator &RegionBegin = Regions[DeleteReg.DefRegion].first;
332 if (RegionBegin == DeleteReg.DefMI)
333 RegionBegin = std::next(MachineBasicBlock::iterator(DeleteReg.DefMI));
334 LIS.RemoveMachineInstrFromMaps(*DeleteReg.DefMI);
335 DeleteReg.DefMI->eraseFromParent();
336 DeleteReg.DefMI = nullptr;
337}
338
341 LiveIntervals &LIS)
342 : Regions(Regions), MRI(MF.getRegInfo()), LIS(LIS),
343 TII(*MF.getSubtarget().getInstrInfo()), TRI(TII.getRegisterInfo()) {
344#ifdef EXPENSIVE_CHECKS
345 // Check that regions are valid.
347 for (const auto &[RegionBegin, RegionEnd] : Regions) {
348 assert(RegionBegin != RegionEnd && "empty region");
349 for (auto MI = RegionBegin; MI != RegionEnd; ++MI) {
350 bool IsNewMI = SeenMIs.insert(&*MI).second;
351 assert(IsNewMI && "overlapping regions");
352 assert(!MI->isTerminator() && "terminator in region");
353 }
354 if (RegionEnd != RegionBegin->getParent()->end()) {
355 bool IsNewMI = SeenMIs.insert(&*RegionEnd).second;
356 assert(IsNewMI && "overlapping regions (upper bound)");
357 }
358 }
359#endif
360}
361
363 Regs.clear();
364 UnrematableOprds.clear();
365 Origins.clear();
366 Rematerializations.clear();
367 RegionMBB.clear();
368 RegToIdx.clear();
369 LISUpdates.clear();
370 if (Regions.empty())
371 return false;
372
373 /// Maps all MIs to their parent region. Region terminators are considered
374 /// part of the region they terminate.
376
377 // Initialize MI to containing region mapping.
378 RegionMBB.reserve(Regions.size());
379 for (unsigned I = 0, E = Regions.size(); I < E; ++I) {
380 RegionBoundaries Region = Regions[I];
381 assert(Region.first != Region.second && "empty cannot be region");
382 for (auto MI = Region.first; MI != Region.second; ++MI) {
383 assert(!MIRegion.contains(&*MI) && "regions should not intersect");
384 MIRegion.insert({&*MI, I});
385 }
387 RegionMBB.push_back(&MBB);
388
389 // A terminator instruction is considered part of the region it terminates.
390 if (Region.second != MBB.end()) {
391 MachineInstr *RegionTerm = &*Region.second;
392 assert(!MIRegion.contains(RegionTerm) && "regions should not intersect");
393 MIRegion.insert({RegionTerm, I});
394 }
395 }
396
397 const unsigned NumVirtRegs = MRI.getNumVirtRegs();
398 BitVector SeenRegs(NumVirtRegs);
399 for (unsigned I = 0, E = NumVirtRegs; I != E; ++I) {
400 if (!SeenRegs[I])
401 addRegIfRematerializable(I, MIRegion, SeenRegs);
402 }
403 assert(Regs.size() == UnrematableOprds.size());
404
405 LLVM_DEBUG({
406 for (RegisterIdx I = 0, E = getNumRegs(); I < E; ++I)
407 dbgs() << printDependencyDAG(I) << '\n';
408 });
409 return !Regs.empty();
410}
411
412void Rematerializer::addRegIfRematerializable(
413 unsigned VirtRegIdx, const DenseMap<MachineInstr *, unsigned> &MIRegion,
414 BitVector &SeenRegs) {
415 assert(!SeenRegs[VirtRegIdx] && "register already seen");
416 Register DefReg = Register::index2VirtReg(VirtRegIdx);
417 SeenRegs.set(VirtRegIdx);
418
419 MachineOperand *MO = MRI.getOneDef(DefReg);
420 if (!MO)
421 return;
422 MachineInstr &DefMI = *MO->getParent();
423 if (!isMIRematerializable(DefMI))
424 return;
425 auto DefRegion = MIRegion.find(&DefMI);
426 if (DefRegion == MIRegion.end())
427 return;
428
429 Reg RematReg;
430 RematReg.DefMI = &DefMI;
431 RematReg.DefRegion = DefRegion->second;
432 unsigned SubIdx = DefMI.getOperand(0).getSubReg();
433 RematReg.Mask = SubIdx ? TRI.getSubRegIndexLaneMask(SubIdx)
434 : MRI.getMaxLaneMaskForVReg(DefReg);
435
436 // Collect the candidate's direct users, both rematerializable and
437 // unrematerializable. MIs outside provided regions cannot be tracked so the
438 // registers they use are not safely rematerializable.
439 for (MachineInstr &UseMI : MRI.use_nodbg_instructions(DefReg)) {
440 if (auto UseRegion = MIRegion.find(&UseMI); UseRegion != MIRegion.end())
441 RematReg.addUser(&UseMI, UseRegion->second);
442 else
443 return;
444 }
445 if (RematReg.Uses.empty())
446 return;
447
448 // Collect the candidate's dependencies. If the same register is used
449 // multiple times we just need to consider it once.
451 SmallVector<unsigned, 2> UnrematDeps;
452 for (const auto &[MOIdx, MO] : enumerate(RematReg.DefMI->operands())) {
453 Register DepReg = getRegDependency(MO);
454 if (!DepReg || !AllDepRegs.insert(DepReg).second)
455 continue;
456 unsigned DepRegIdx = DepReg.virtRegIndex();
457 if (!SeenRegs[DepRegIdx])
458 addRegIfRematerializable(DepRegIdx, MIRegion, SeenRegs);
459 if (auto DepIt = RegToIdx.find(DepReg); DepIt != RegToIdx.end())
460 RematReg.Dependencies.push_back(Reg::Dependency(MOIdx, DepIt->second));
461 else
462 UnrematDeps.push_back(MOIdx);
463 }
464
465 // The register is rematerializable.
466 RegToIdx.insert({DefReg, Regs.size()});
467 Regs.push_back(RematReg);
468 UnrematableOprds.push_back(UnrematDeps);
469}
470
471bool Rematerializer::isMIRematerializable(const MachineInstr &MI) const {
472 if (!TII.isReMaterializable(MI))
473 return false;
474
475 assert(MI.getOperand(0).getReg().isVirtual() && "should be virtual");
476 assert(MRI.hasOneDef(MI.getOperand(0).getReg()) && "should have single def");
477
478 for (const MachineOperand &MO : MI.all_uses()) {
479 // We can't remat physreg uses, unless it is a constant or an ignorable
480 // use (e.g. implicit exec use on VALU instructions)
481 if (MO.getReg().isPhysical()) {
482 if (MRI.isConstantPhysReg(MO.getReg()) || TII.isIgnorableUse(MO))
483 continue;
484 return false;
485 }
486 }
487
488 return true;
489}
490
492 if (!MI.getNumOperands() || !MI.getOperand(0).isReg() ||
493 MI.getOperand(0).readsReg())
494 return NoReg;
495 Register Reg = MI.getOperand(0).getReg();
496 auto UserRegIt = RegToIdx.find(Reg);
497 if (UserRegIt == RegToIdx.end())
498 return NoReg;
499 return UserRegIt->second;
500}
501
503 RegisterIdx RegIdx, unsigned UseRegion,
505 SmallVectorImpl<Reg::Dependency> &&Dependencies) {
506 RegisterIdx NewRegIdx = Regs.size();
507
508 Reg &NewReg = Regs.emplace_back();
509 Reg &FromReg = Regs[RegIdx];
510 NewReg.Mask = FromReg.Mask;
511 NewReg.DefRegion = UseRegion;
512 NewReg.Dependencies = std::move(Dependencies);
513
514 // Track rematerialization link between registers. Origins are always
515 // registers that existed originally, and rematerializations are always
516 // attached to them.
517 const RegisterIdx OriginIdx = getOriginOrSelf(RegIdx);
518 Origins.push_back(OriginIdx);
519 Rematerializations[OriginIdx].insert(NewRegIdx);
520
521 // Use the TII to rematerialize the defining instruction with a new defined
522 // register.
523 Register NewDefReg = MRI.cloneVirtualRegister(FromReg.getDefReg());
524 TII.reMaterialize(*RegionMBB[UseRegion], InsertPos, NewDefReg, 0,
525 *FromReg.DefMI);
526 NewReg.DefMI = &*std::prev(InsertPos);
527 RegToIdx.insert({NewDefReg, NewRegIdx});
528 postRematerialization(RegIdx, NewRegIdx, InsertPos);
529
530 noteRegCreated(NewRegIdx);
531 LLVM_DEBUG(dbgs() << "** Rematerialized " << printID(RegIdx) << " as "
532 << printRematReg(NewRegIdx) << '\n');
533 return NewRegIdx;
534}
535
537 RegisterIdx RegIdx, unsigned DefRegion,
538 MachineBasicBlock::iterator InsertPos, Register DefReg,
539 SmallVectorImpl<Reg::Dependency> &&Dependencies) {
540 assert(RegToIdx.contains(DefReg) && "unknown defined register");
541 assert(RegToIdx.at(DefReg) == RegIdx && "incorrect defined register");
542 assert(!getReg(RegIdx).DefMI && "register is still alive");
543
544 Reg &OriginReg = Regs[RegIdx];
545 OriginReg.DefRegion = DefRegion;
546 OriginReg.Dependencies = std::move(Dependencies);
547
548 // Re-establish the link between origin and rematerialization if necessary.
549 const bool RecreateOriginalReg = isOriginalRegister(RegIdx);
550 if (!RecreateOriginalReg)
551 Rematerializations[getOriginOf(RegIdx)].insert(RegIdx);
552
553 // Rematerialize from one of the existing rematerializations or from the
554 // origin. We expect at least one to exist, otherwise it would mean the value
555 // held by the original register is no longer available anywhere in the MF.
556 RegisterIdx ModelRegIdx;
557 if (RecreateOriginalReg) {
558 assert(Rematerializations.contains(RegIdx) && "expected remats");
559 ModelRegIdx = *Rematerializations.at(RegIdx).begin();
560 } else {
561 assert(getReg(getOriginOf(RegIdx)).DefMI && "expected alive origin");
562 ModelRegIdx = getOriginOf(RegIdx);
563 }
564 const MachineInstr &ModelDefMI = *getReg(ModelRegIdx).DefMI;
565
566 TII.reMaterialize(*RegionMBB[DefRegion], InsertPos, DefReg, 0, ModelDefMI);
567 OriginReg.DefMI = &*std::prev(InsertPos);
568 postRematerialization(ModelRegIdx, RegIdx, InsertPos);
569 LLVM_DEBUG(dbgs() << "** Recreated " << printID(RegIdx) << " as "
570 << printRematReg(RegIdx) << '\n');
571}
572
573void Rematerializer::postRematerialization(
574 RegisterIdx ModelRegIdx, RegisterIdx RematRegIdx,
575 MachineBasicBlock::iterator InsertPos) {
576
577 // The start of the new register's region may have changed.
578 Reg &ModelReg = Regs[ModelRegIdx], &RematReg = Regs[RematRegIdx];
579 LIS.InsertMachineInstrInMaps(*RematReg.DefMI);
580 MachineBasicBlock::iterator &RegionBegin = Regions[RematReg.DefRegion].first;
581 if (RegionBegin == std::next(MachineBasicBlock::iterator(RematReg.DefMI)))
582 RegionBegin = RematReg.DefMI;
583
584 // Replace dependencies as needed in the rematerialized MI. All dependencies
585 // of the latter gain a new user.
586 auto ZipedDeps = zip_equal(ModelReg.Dependencies, RematReg.Dependencies);
587 for (const auto &[OldDep, NewDep] : ZipedDeps) {
588 assert(OldDep.MOIdx == NewDep.MOIdx && "operand mismatch");
589 LLVM_DEBUG(dbgs() << " Operand #" << OldDep.MOIdx << ": "
590 << printID(OldDep.RegIdx) << " -> "
591 << printID(NewDep.RegIdx) << '\n');
592
593 Reg &NewDepReg = Regs[NewDep.RegIdx];
594 if (OldDep.RegIdx != NewDep.RegIdx) {
595 Register OldDefReg = ModelReg.DefMI->getOperand(OldDep.MOIdx).getReg();
596 RematReg.DefMI->substituteRegister(OldDefReg, NewDepReg.getDefReg(), 0,
597 TRI);
598 LISUpdates.insert(OldDep.RegIdx);
599 }
600 NewDepReg.addUser(RematReg.DefMI, RematReg.DefRegion);
601 LISUpdates.insert(NewDep.RegIdx);
602 }
603}
604
605std::pair<MachineInstr *, MachineInstr *>
607 const LiveIntervals &LIS) const {
608 auto It = Uses.find(UseRegion);
609 if (It == Uses.end())
610 return {nullptr, nullptr};
611 const RegionUsers &RegionUsers = It->getSecond();
612 assert(!RegionUsers.empty() && "empty userset in region");
613
614 auto User = RegionUsers.begin(), UserEnd = RegionUsers.end();
615 MachineInstr *FirstMI = *User, *LastMI = FirstMI;
616 SlotIndex FirstIndex = LIS.getInstructionIndex(*FirstMI),
617 LastIndex = FirstIndex;
618
619 while (++User != UserEnd) {
620 SlotIndex UserIndex = LIS.getInstructionIndex(**User);
621 if (UserIndex < FirstIndex) {
622 FirstIndex = UserIndex;
623 FirstMI = *User;
624 } else if (UserIndex > LastIndex) {
625 LastIndex = UserIndex;
626 LastMI = *User;
627 }
628 }
629
630 return {FirstMI, LastMI};
631}
632
633void Rematerializer::Reg::addUser(MachineInstr *MI, unsigned Region) {
634 Uses[Region].insert(MI);
635}
636
637void Rematerializer::Reg::addUsers(const RegionUsers &NewUsers,
638 unsigned Region) {
639 Uses[Region].insert_range(NewUsers);
640}
641
642void Rematerializer::Reg::eraseUser(MachineInstr *MI, unsigned Region) {
643 RegionUsers &RUsers = Uses.at(Region);
644 assert(RUsers.contains(MI) && "user not in region");
645 if (RUsers.size() == 1)
646 Uses.erase(Region);
647 else
648 RUsers.erase(MI);
649}
650
652 return Printable([&, RootIdx](raw_ostream &OS) {
654 std::function<void(RegisterIdx, unsigned)> WalkTree =
655 [&](RegisterIdx RegIdx, unsigned Depth) -> void {
656 unsigned MaxDepth = std::max(RegDepths.lookup_or(RegIdx, Depth), Depth);
657 RegDepths.emplace_or_assign(RegIdx, MaxDepth);
658 for (const Reg::Dependency &Dep : getReg(RegIdx).Dependencies)
659 WalkTree(Dep.RegIdx, Depth + 1);
660 };
661 WalkTree(RootIdx, 0);
662
663 // Sort in decreasing depth order to print root at the bottom.
665 RegDepths.end());
666 sort(Regs, [](const auto &LHS, const auto &RHS) {
667 return LHS.second > RHS.second;
668 });
669
670 OS << printID(RootIdx) << " has " << Regs.size() - 1 << " dependencies\n";
671 for (const auto &[RegIdx, Depth] : Regs) {
672 OS << indent(Depth, 2) << (Depth ? '|' : '*') << ' '
673 << printRematReg(RegIdx, /*SkipRegions=*/Depth) << '\n';
674 }
675 OS << printRegUsers(RootIdx);
676 });
677}
678
680 return Printable([&, RegIdx](raw_ostream &OS) {
681 const Reg &PrintReg = getReg(RegIdx);
682 OS << '(' << RegIdx << '/';
683 if (!PrintReg.DefMI) {
684 OS << "<dead>";
685 } else {
686 OS << printReg(PrintReg.getDefReg(), &TRI,
687 PrintReg.DefMI->getOperand(0).getSubReg(), &MRI);
688 }
689 OS << ")[" << PrintReg.DefRegion << "]";
690 });
691}
692
694 bool SkipRegions) const {
695 return Printable([&, RegIdx, SkipRegions](raw_ostream &OS) {
696 const Reg &PrintReg = getReg(RegIdx);
697 if (!SkipRegions) {
698 OS << printID(RegIdx) << " [" << PrintReg.DefRegion;
699 if (!PrintReg.Uses.empty()) {
700 assert(PrintReg.DefMI && "dead register cannot have uses");
701 const LiveInterval &LI = LIS.getInterval(PrintReg.getDefReg());
702 // First display all regions in which the register is live-through and
703 // not used.
704 bool First = true;
705 for (const auto [I, Bounds] : enumerate(Regions)) {
706 if (Bounds.first == Bounds.second)
707 continue;
708 if (!PrintReg.Uses.contains(I) &&
709 LI.liveAt(LIS.getInstructionIndex(*Bounds.first)) &&
710 LI.liveAt(LIS.getInstructionIndex(*std::prev(Bounds.second))
711 .getRegSlot())) {
712 OS << (First ? " - " : ",") << I;
713 First = false;
714 }
715 }
716 OS << (First ? " --> " : " -> ");
717
718 // Then display regions in which the register is used.
719 auto It = PrintReg.Uses.begin();
720 OS << It->first;
721 while (++It != PrintReg.Uses.end())
722 OS << "," << It->first;
723 }
724 OS << "] ";
725 }
726 OS << printID(RegIdx) << ' ';
727 PrintReg.DefMI->print(OS, /*IsStandalone=*/true, /*SkipOpers=*/false,
728 /*SkipDebugLoc=*/false, /*AddNewLine=*/false);
729 OS << " @ ";
730 LIS.getInstructionIndex(*PrintReg.DefMI).print(OS);
731 });
732}
733
735 return Printable([&, RegIdx](raw_ostream &OS) {
736 for (const auto &[UseRegion, Users] : getReg(RegIdx).Uses) {
737 for (MachineInstr *MI : Users)
738 OS << " User " << printUser(MI, UseRegion) << '\n';
739 }
740 });
741}
742
744 std::optional<unsigned> UseRegion) const {
745 return Printable([&, MI, UseRegion](raw_ostream &OS) {
746 RegisterIdx RegIdx = getDefRegIdx(*MI);
747 if (RegIdx != NoReg) {
748 OS << printID(RegIdx);
749 } else {
750 OS << "(-/-)[";
751 if (UseRegion)
752 OS << *UseRegion;
753 else
754 OS << '?';
755 OS << ']';
756 }
757 OS << ' ';
758 MI->print(OS, /*IsStandalone=*/true, /*SkipOpers=*/false,
759 /*SkipDebugLoc=*/false, /*AddNewLine=*/false);
760 OS << " @ ";
761 LIS.getInstructionIndex(*MI).print(OS);
762 });
763}
764
765Rollbacker::RollbackInfo::RollbackInfo(const Rematerializer &Remater,
766 RegisterIdx RegIdx) {
767 const Rematerializer::Reg &Reg = Remater.getReg(RegIdx);
768 DefReg = Reg.getDefReg();
769 DefRegion = Reg.DefRegion;
770 Dependencies = Reg.Dependencies;
771
772 InsertPos = std::next(Reg.DefMI->getIterator());
773 if (InsertPos != Reg.DefMI->getParent()->end())
774 NextRegIdx = Remater.getDefRegIdx(*InsertPos);
775 else
776 NextRegIdx = Rematerializer::NoReg;
777}
778
780 RegisterIdx RegIdx) {
781 if (RollingBack)
782 return;
783 Rematerializations[Remater.getOriginOf(RegIdx)].insert(RegIdx);
784}
785
787 RegisterIdx RegIdx) {
788 if (RollingBack || Remater.isRematerializedRegister(RegIdx))
789 return;
790 DeadRegs.try_emplace(RegIdx, Remater, RegIdx);
791}
792
794 RollingBack = true;
795
796 // Re-create deleted registers.
797 for (auto &[RegIdx, Info] : DeadRegs) {
798 assert(!Remater.getReg(RegIdx).isAlive() && "register should be dead");
799
800 // The MI that was originally just after the MI defining the register we
801 // are trying to re-create may have been deleted. In such cases, we can
802 // re-create at that MI's own insert position (and apply the same logic
803 // recursively).
804 MachineBasicBlock::iterator InsertPos = Info.InsertPos;
805 RegisterIdx NextRegIdx = Info.NextRegIdx;
806 while (NextRegIdx != Rematerializer::NoReg) {
807 const auto *NextRegRollback = DeadRegs.find(NextRegIdx);
808 if (NextRegRollback == DeadRegs.end())
809 break;
810 InsertPos = NextRegRollback->second.InsertPos;
811 NextRegIdx = NextRegRollback->second.NextRegIdx;
812 }
813 Remater.recreateReg(RegIdx, Info.DefRegion, InsertPos, Info.DefReg,
814 std::move(Info.Dependencies));
815 }
816
817 // Rollback rematerializations.
818 for (const auto &[RegIdx, RematsOf] : Rematerializations) {
819 for (RegisterIdx RematRegIdx : RematsOf) {
820 // It is possible that rematerializations were deleted. Their users would
821 // have been transfered to some other rematerialization so we can safely
822 // ignore them. Original registers that were deleted were just re-created
823 // so we do not need to check for that.
824 if (Remater.getReg(RematRegIdx).isAlive())
825 Remater.transferAllUsers(RematRegIdx, RegIdx);
826 }
827 }
828
829 Remater.updateLiveIntervals();
830 DeadRegs.clear();
831 Rematerializations.clear();
832 RollingBack = false;
833}
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:119
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
BitVector & set()
Set all bits in the bitvector.
Definition BitVector.h:366
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:225
std::pair< iterator, bool > emplace_or_assign(const KeyT &Key, Ts &&...Args)
Definition DenseMap.h:360
iterator begin()
Definition DenseMap.h:139
iterator end()
Definition DenseMap.h:143
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:216
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
Definition DenseMap.h:262
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:286
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Definition DenseMap.h:178
Implements a dense probed hash-table based set.
Definition DenseSet.h:289
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.
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 rematerializeReg(RegisterIdx RegIdx, unsigned UseRegion, MachineBasicBlock::iterator InsertPos, SmallVectorImpl< Reg::Dependency > &&Dependencies)
Rematerializes register RegIdx before InsertPos in UseRegion, adding the new rematerializable registe...
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 void updateLiveIntervals()
Recomputes all live intervals that have changed as a result of previous rematerializations.
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 ...
unsigned RegisterIdx
Index type for rematerializable registers.
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.
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 ...
ArrayRef< unsigned > getUnrematableOprds(RegisterIdx RegIdx) const
Returns operand indices corresponding to unrematerializable operands for any register RegIdx.
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...
bool isRematerializedRegister(RegisterIdx RegIdx) const
Whether register RegIdx is a rematerialization of some original register.
LLVM_ABI 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.
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 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 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:301
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:212
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:840
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:2553
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1635
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
@ 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.
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.
SmallDenseSet< MachineInstr *, 4 > RegionUsers