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: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: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: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