1//===- DetectDeadLanes.cpp - SubRegister Lane Usage Analysis --*- 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/// Analysis that tracks defined/used subregister lanes across COPY instructions
11/// and instructions that get lowered to a COPY (PHI, REG_SEQUENCE,
12/// INSERT_SUBREG, EXTRACT_SUBREG).
13/// The information is used to detect dead definitions and the usage of
14/// (completely) undefined values and mark the operands as such.
15/// This pass is necessary because the dead/undef status is not obvious anymore
16/// when subregisters are involved.
17///
18/// Example:
19/// %0 = some definition
20/// %1 = IMPLICIT_DEF
21/// %2 = REG_SEQUENCE %0, sub0, %1, sub1
22/// %3 = EXTRACT_SUBREG %2, sub1
23/// = use %3
24/// The %0 definition is dead and %3 contains an undefined value.
25//
26//===----------------------------------------------------------------------===//
27
28#include "llvm/CodeGen/DetectDeadLanes.h"
29#include "llvm/CodeGen/MachineFunctionPass.h"
30#include "llvm/CodeGen/MachineRegisterInfo.h"
31#include "llvm/CodeGen/TargetRegisterInfo.h"
32#include "llvm/InitializePasses.h"
33#include "llvm/Pass.h"
34#include "llvm/Support/Debug.h"
35#include "llvm/Support/raw_ostream.h"
36
37using namespace llvm;
38
39#define DEBUG_TYPE "detect-dead-lanes"
40
41DeadLaneDetector::DeadLaneDetector(const MachineRegisterInfo *MRI,
42 const TargetRegisterInfo *TRI)
43 : MRI(MRI), TRI(TRI) {
44 unsigned NumVirtRegs = MRI->getNumVirtRegs();
45 VRegInfos = std::unique_ptr<VRegInfo[]>(new VRegInfo[NumVirtRegs]);
46 WorklistMembers.resize(N: NumVirtRegs);
47 DefinedByCopy.resize(N: NumVirtRegs);
48}
49
50/// Returns true if \p MI will get lowered to a series of COPY instructions.
51/// We call this a COPY-like instruction.
52static bool lowersToCopies(const MachineInstr &MI) {
53 // Note: We could support instructions with MCInstrDesc::isRegSequenceLike(),
54 // isExtractSubRegLike(), isInsertSubregLike() in the future even though they
55 // are not lowered to a COPY.
56 switch (MI.getOpcode()) {
57 case TargetOpcode::COPY:
58 case TargetOpcode::PHI:
59 case TargetOpcode::INSERT_SUBREG:
60 case TargetOpcode::REG_SEQUENCE:
61 case TargetOpcode::EXTRACT_SUBREG:
62 return true;
63 }
64 return false;
65}
66
67static bool isCrossCopy(const MachineRegisterInfo &MRI,
68 const MachineInstr &MI,
69 const TargetRegisterClass *DstRC,
70 const MachineOperand &MO) {
71 assert(lowersToCopies(MI));
72 Register SrcReg = MO.getReg();
73 const TargetRegisterClass *SrcRC = MRI.getRegClass(Reg: SrcReg);
74 if (DstRC == SrcRC)
75 return false;
76
77 unsigned SrcSubIdx = MO.getSubReg();
78
79 const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
80 unsigned DstSubIdx = 0;
81 switch (MI.getOpcode()) {
82 case TargetOpcode::INSERT_SUBREG:
83 if (MO.getOperandNo() == 2)
84 DstSubIdx = MI.getOperand(i: 3).getImm();
85 break;
86 case TargetOpcode::REG_SEQUENCE: {
87 unsigned OpNum = MO.getOperandNo();
88 DstSubIdx = MI.getOperand(i: OpNum+1).getImm();
89 break;
90 }
91 case TargetOpcode::EXTRACT_SUBREG: {
92 unsigned SubReg = MI.getOperand(i: 2).getImm();
93 SrcSubIdx = TRI.composeSubRegIndices(a: SubReg, b: SrcSubIdx);
94 }
95 }
96
97 return !TRI.findCommonRegClass(DefRC: SrcRC, DefSubReg: SrcSubIdx, SrcRC: DstRC, SrcSubReg: DstSubIdx);
98}
99
100void DeadLaneDetector::addUsedLanesOnOperand(const MachineOperand &MO,
101 LaneBitmask UsedLanes) {
102 if (!MO.readsReg())
103 return;
104 Register MOReg = MO.getReg();
105 if (!MOReg.isVirtual())
106 return;
107
108 unsigned MOSubReg = MO.getSubReg();
109 if (MOSubReg != 0)
110 UsedLanes = TRI->composeSubRegIndexLaneMask(IdxA: MOSubReg, Mask: UsedLanes);
111 UsedLanes &= MRI->getMaxLaneMaskForVReg(Reg: MOReg);
112
113 unsigned MORegIdx = MOReg.virtRegIndex();
114 DeadLaneDetector::VRegInfo &MORegInfo = VRegInfos[MORegIdx];
115 LaneBitmask PrevUsedLanes = MORegInfo.UsedLanes;
116 // Any change at all?
117 if ((UsedLanes & ~PrevUsedLanes).none())
118 return;
119
120 // Set UsedLanes and remember instruction for further propagation.
121 MORegInfo.UsedLanes = PrevUsedLanes | UsedLanes;
122 if (DefinedByCopy.test(Idx: MORegIdx))
123 PutInWorklist(RegIdx: MORegIdx);
124}
125
126void DeadLaneDetector::transferUsedLanesStep(const MachineInstr &MI,
127 LaneBitmask UsedLanes) {
128 for (const MachineOperand &MO : MI.uses()) {
129 if (!MO.isReg() || !MO.getReg().isVirtual())
130 continue;
131 LaneBitmask UsedOnMO = transferUsedLanes(MI, UsedLanes, MO);
132 addUsedLanesOnOperand(MO, UsedLanes: UsedOnMO);
133 }
134}
135
136LaneBitmask
137DeadLaneDetector::transferUsedLanes(const MachineInstr &MI,
138 LaneBitmask UsedLanes,
139 const MachineOperand &MO) const {
140 unsigned OpNum = MO.getOperandNo();
141 assert(lowersToCopies(MI) &&
142 DefinedByCopy[MI.getOperand(0).getReg().virtRegIndex()]);
143
144 switch (MI.getOpcode()) {
145 case TargetOpcode::COPY:
146 case TargetOpcode::PHI:
147 return UsedLanes;
148 case TargetOpcode::REG_SEQUENCE: {
149 assert(OpNum % 2 == 1);
150 unsigned SubIdx = MI.getOperand(i: OpNum + 1).getImm();
151 return TRI->reverseComposeSubRegIndexLaneMask(IdxA: SubIdx, LaneMask: UsedLanes);
152 }
153 case TargetOpcode::INSERT_SUBREG: {
154 unsigned SubIdx = MI.getOperand(i: 3).getImm();
155 LaneBitmask MO2UsedLanes =
156 TRI->reverseComposeSubRegIndexLaneMask(IdxA: SubIdx, LaneMask: UsedLanes);
157 if (OpNum == 2)
158 return MO2UsedLanes;
159
160 const MachineOperand &Def = MI.getOperand(i: 0);
161 Register DefReg = Def.getReg();
162 const TargetRegisterClass *RC = MRI->getRegClass(Reg: DefReg);
163 LaneBitmask MO1UsedLanes;
164 if (RC->CoveredBySubRegs)
165 MO1UsedLanes = UsedLanes & ~TRI->getSubRegIndexLaneMask(SubIdx);
166 else
167 MO1UsedLanes = RC->LaneMask;
168
169 assert(OpNum == 1);
170 return MO1UsedLanes;
171 }
172 case TargetOpcode::EXTRACT_SUBREG: {
173 assert(OpNum == 1);
174 unsigned SubIdx = MI.getOperand(i: 2).getImm();
175 return TRI->composeSubRegIndexLaneMask(IdxA: SubIdx, Mask: UsedLanes);
176 }
177 default:
178 llvm_unreachable("function must be called with COPY-like instruction");
179 }
180}
181
182void DeadLaneDetector::transferDefinedLanesStep(const MachineOperand &Use,
183 LaneBitmask DefinedLanes) {
184 if (!Use.readsReg())
185 return;
186 // Check whether the operand writes a vreg and is part of a COPY-like
187 // instruction.
188 const MachineInstr &MI = *Use.getParent();
189 if (MI.getDesc().getNumDefs() != 1)
190 return;
191 // FIXME: PATCHPOINT instructions announce a Def that does not always exist,
192 // they really need to be modeled differently!
193 if (MI.getOpcode() == TargetOpcode::PATCHPOINT)
194 return;
195 const MachineOperand &Def = *MI.defs().begin();
196 Register DefReg = Def.getReg();
197 if (!DefReg.isVirtual())
198 return;
199 unsigned DefRegIdx = DefReg.virtRegIndex();
200 if (!DefinedByCopy.test(Idx: DefRegIdx))
201 return;
202
203 unsigned OpNum = Use.getOperandNo();
204 DefinedLanes =
205 TRI->reverseComposeSubRegIndexLaneMask(IdxA: Use.getSubReg(), LaneMask: DefinedLanes);
206 DefinedLanes = transferDefinedLanes(Def, OpNum, DefinedLanes);
207
208 VRegInfo &RegInfo = VRegInfos[DefRegIdx];
209 LaneBitmask PrevDefinedLanes = RegInfo.DefinedLanes;
210 // Any change at all?
211 if ((DefinedLanes & ~PrevDefinedLanes).none())
212 return;
213
214 RegInfo.DefinedLanes = PrevDefinedLanes | DefinedLanes;
215 PutInWorklist(RegIdx: DefRegIdx);
216}
217
218LaneBitmask DeadLaneDetector::transferDefinedLanes(
219 const MachineOperand &Def, unsigned OpNum, LaneBitmask DefinedLanes) const {
220 const MachineInstr &MI = *Def.getParent();
221 // Translate DefinedLanes if necessary.
222 switch (MI.getOpcode()) {
223 case TargetOpcode::REG_SEQUENCE: {
224 unsigned SubIdx = MI.getOperand(i: OpNum + 1).getImm();
225 DefinedLanes = TRI->composeSubRegIndexLaneMask(IdxA: SubIdx, Mask: DefinedLanes);
226 DefinedLanes &= TRI->getSubRegIndexLaneMask(SubIdx);
227 break;
228 }
229 case TargetOpcode::INSERT_SUBREG: {
230 unsigned SubIdx = MI.getOperand(i: 3).getImm();
231 if (OpNum == 2) {
232 DefinedLanes = TRI->composeSubRegIndexLaneMask(IdxA: SubIdx, Mask: DefinedLanes);
233 DefinedLanes &= TRI->getSubRegIndexLaneMask(SubIdx);
234 } else {
235 assert(OpNum == 1 && "INSERT_SUBREG must have two operands");
236 // Ignore lanes defined by operand 2.
237 DefinedLanes &= ~TRI->getSubRegIndexLaneMask(SubIdx);
238 }
239 break;
240 }
241 case TargetOpcode::EXTRACT_SUBREG: {
242 unsigned SubIdx = MI.getOperand(i: 2).getImm();
243 assert(OpNum == 1 && "EXTRACT_SUBREG must have one register operand only");
244 DefinedLanes = TRI->reverseComposeSubRegIndexLaneMask(IdxA: SubIdx, LaneMask: DefinedLanes);
245 break;
246 }
247 case TargetOpcode::COPY:
248 case TargetOpcode::PHI:
249 break;
250 default:
251 llvm_unreachable("function must be called with COPY-like instruction");
252 }
253
254 assert(Def.getSubReg() == 0 &&
255 "Should not have subregister defs in machine SSA phase");
256 DefinedLanes &= MRI->getMaxLaneMaskForVReg(Reg: Def.getReg());
257 return DefinedLanes;
258}
259
260LaneBitmask DeadLaneDetector::determineInitialDefinedLanes(Register Reg) {
261 // Live-In or unused registers have no definition but are considered fully
262 // defined.
263 if (!MRI->hasOneDef(RegNo: Reg))
264 return LaneBitmask::getAll();
265
266 const MachineOperand &Def = *MRI->def_begin(RegNo: Reg);
267 const MachineInstr &DefMI = *Def.getParent();
268 if (lowersToCopies(MI: DefMI)) {
269 // Start optimisatically with no used or defined lanes for copy
270 // instructions. The following dataflow analysis will add more bits.
271 unsigned RegIdx = Register(Reg).virtRegIndex();
272 DefinedByCopy.set(RegIdx);
273 PutInWorklist(RegIdx);
274
275 if (Def.isDead())
276 return LaneBitmask::getNone();
277
278 // COPY/PHI can copy across unrelated register classes (example: float/int)
279 // with incompatible subregister structure. Do not include these in the
280 // dataflow analysis since we cannot transfer lanemasks in a meaningful way.
281 const TargetRegisterClass *DefRC = MRI->getRegClass(Reg);
282
283 // Determine initially DefinedLanes.
284 LaneBitmask DefinedLanes;
285 for (const MachineOperand &MO : DefMI.uses()) {
286 if (!MO.isReg() || !MO.readsReg())
287 continue;
288 Register MOReg = MO.getReg();
289 if (!MOReg)
290 continue;
291
292 LaneBitmask MODefinedLanes;
293 if (MOReg.isPhysical()) {
294 MODefinedLanes = LaneBitmask::getAll();
295 } else if (isCrossCopy(MRI: *MRI, MI: DefMI, DstRC: DefRC, MO)) {
296 MODefinedLanes = LaneBitmask::getAll();
297 } else {
298 assert(MOReg.isVirtual());
299 if (MRI->hasOneDef(RegNo: MOReg)) {
300 const MachineOperand &MODef = *MRI->def_begin(RegNo: MOReg);
301 const MachineInstr &MODefMI = *MODef.getParent();
302 // Bits from copy-like operations will be added later.
303 if (lowersToCopies(MI: MODefMI) || MODefMI.isImplicitDef())
304 continue;
305 }
306 unsigned MOSubReg = MO.getSubReg();
307 MODefinedLanes = MRI->getMaxLaneMaskForVReg(Reg: MOReg);
308 MODefinedLanes = TRI->reverseComposeSubRegIndexLaneMask(
309 IdxA: MOSubReg, LaneMask: MODefinedLanes);
310 }
311
312 unsigned OpNum = MO.getOperandNo();
313 DefinedLanes |= transferDefinedLanes(Def, OpNum, DefinedLanes: MODefinedLanes);
314 }
315 return DefinedLanes;
316 }
317 if (DefMI.isImplicitDef() || Def.isDead())
318 return LaneBitmask::getNone();
319
320 assert(Def.getSubReg() == 0 &&
321 "Should not have subregister defs in machine SSA phase");
322 return MRI->getMaxLaneMaskForVReg(Reg);
323}
324
325LaneBitmask DeadLaneDetector::determineInitialUsedLanes(Register Reg) {
326 LaneBitmask UsedLanes = LaneBitmask::getNone();
327 for (const MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
328 if (!MO.readsReg())
329 continue;
330
331 const MachineInstr &UseMI = *MO.getParent();
332 if (UseMI.isKill())
333 continue;
334
335 unsigned SubReg = MO.getSubReg();
336 if (lowersToCopies(MI: UseMI)) {
337 assert(UseMI.getDesc().getNumDefs() == 1);
338 const MachineOperand &Def = *UseMI.defs().begin();
339 Register DefReg = Def.getReg();
340 // The used lanes of COPY-like instruction operands are determined by the
341 // following dataflow analysis.
342 if (DefReg.isVirtual()) {
343 // But ignore copies across incompatible register classes.
344 bool CrossCopy = false;
345 if (lowersToCopies(MI: UseMI)) {
346 const TargetRegisterClass *DstRC = MRI->getRegClass(Reg: DefReg);
347 CrossCopy = isCrossCopy(MRI: *MRI, MI: UseMI, DstRC, MO);
348 if (CrossCopy)
349 LLVM_DEBUG(dbgs() << "Copy across incompatible classes: " << UseMI);
350 }
351
352 if (!CrossCopy)
353 continue;
354 }
355 }
356
357 // Shortcut: All lanes are used.
358 if (SubReg == 0)
359 return MRI->getMaxLaneMaskForVReg(Reg);
360
361 UsedLanes |= TRI->getSubRegIndexLaneMask(SubIdx: SubReg);
362 }
363 return UsedLanes;
364}
365
366namespace {
367
368class DetectDeadLanes {
369public:
370 bool run(MachineFunction &MF);
371
372private:
373 /// update the operand status.
374 /// The first return value shows whether MF been changed.
375 /// The second return value indicates we need to call
376 /// DeadLaneDetector::computeSubRegisterLaneBitInfo and this function again
377 /// to propagate changes.
378 std::pair<bool, bool>
379 modifySubRegisterOperandStatus(const DeadLaneDetector &DLD,
380 MachineFunction &MF);
381
382 bool isUndefRegAtInput(const MachineOperand &MO,
383 const DeadLaneDetector::VRegInfo &RegInfo) const;
384
385 bool isUndefInput(const DeadLaneDetector &DLD, const MachineOperand &MO,
386 bool *CrossCopy) const;
387
388 const MachineRegisterInfo *MRI = nullptr;
389 const TargetRegisterInfo *TRI = nullptr;
390};
391
392struct DetectDeadLanesLegacy : public MachineFunctionPass {
393 static char ID;
394 DetectDeadLanesLegacy() : MachineFunctionPass(ID) {}
395
396 StringRef getPassName() const override { return "Detect Dead Lanes"; }
397
398 void getAnalysisUsage(AnalysisUsage &AU) const override {
399 AU.setPreservesCFG();
400 MachineFunctionPass::getAnalysisUsage(AU);
401 }
402
403 bool runOnMachineFunction(MachineFunction &MF) override {
404 return DetectDeadLanes().run(MF);
405 }
406};
407
408} // end anonymous namespace
409
410char DetectDeadLanesLegacy::ID = 0;
411char &llvm::DetectDeadLanesID = DetectDeadLanesLegacy::ID;
412
413INITIALIZE_PASS(DetectDeadLanesLegacy, DEBUG_TYPE, "Detect Dead Lanes", false,
414 false)
415
416bool DetectDeadLanes::isUndefRegAtInput(
417 const MachineOperand &MO, const DeadLaneDetector::VRegInfo &RegInfo) const {
418 unsigned SubReg = MO.getSubReg();
419 LaneBitmask Mask = TRI->getSubRegIndexLaneMask(SubIdx: SubReg);
420 return (RegInfo.DefinedLanes & RegInfo.UsedLanes & Mask).none();
421}
422
423bool DetectDeadLanes::isUndefInput(const DeadLaneDetector &DLD,
424 const MachineOperand &MO,
425 bool *CrossCopy) const {
426 if (!MO.isUse())
427 return false;
428 const MachineInstr &MI = *MO.getParent();
429 if (!lowersToCopies(MI))
430 return false;
431 const MachineOperand &Def = MI.getOperand(i: 0);
432 Register DefReg = Def.getReg();
433 if (!DefReg.isVirtual())
434 return false;
435 unsigned DefRegIdx = DefReg.virtRegIndex();
436 if (!DLD.isDefinedByCopy(RegIdx: DefRegIdx))
437 return false;
438
439 const DeadLaneDetector::VRegInfo &DefRegInfo = DLD.getVRegInfo(RegIdx: DefRegIdx);
440 LaneBitmask UsedLanes = DLD.transferUsedLanes(MI, UsedLanes: DefRegInfo.UsedLanes, MO);
441 if (UsedLanes.any())
442 return false;
443
444 Register MOReg = MO.getReg();
445 if (MOReg.isVirtual()) {
446 const TargetRegisterClass *DstRC = MRI->getRegClass(Reg: DefReg);
447 *CrossCopy = isCrossCopy(MRI: *MRI, MI, DstRC, MO);
448 }
449 return true;
450}
451
452void DeadLaneDetector::computeSubRegisterLaneBitInfo() {
453 // First pass: Populate defs/uses of vregs with initial values
454 unsigned NumVirtRegs = MRI->getNumVirtRegs();
455 for (unsigned RegIdx = 0; RegIdx < NumVirtRegs; ++RegIdx) {
456 Register Reg = Register::index2VirtReg(Index: RegIdx);
457
458 // Determine used/defined lanes and add copy instructions to worklist.
459 VRegInfo &Info = VRegInfos[RegIdx];
460 Info.DefinedLanes = determineInitialDefinedLanes(Reg);
461 Info.UsedLanes = determineInitialUsedLanes(Reg);
462 }
463
464 // Iterate as long as defined lanes/used lanes keep changing.
465 while (!Worklist.empty()) {
466 unsigned RegIdx = Worklist.front();
467 Worklist.pop_front();
468 WorklistMembers.reset(Idx: RegIdx);
469 VRegInfo &Info = VRegInfos[RegIdx];
470 Register Reg = Register::index2VirtReg(Index: RegIdx);
471
472 // Transfer UsedLanes to operands of DefMI (backwards dataflow).
473 MachineOperand &Def = *MRI->def_begin(RegNo: Reg);
474 const MachineInstr &MI = *Def.getParent();
475 transferUsedLanesStep(MI, UsedLanes: Info.UsedLanes);
476 // Transfer DefinedLanes to users of Reg (forward dataflow).
477 for (const MachineOperand &MO : MRI->use_nodbg_operands(Reg))
478 transferDefinedLanesStep(Use: MO, DefinedLanes: Info.DefinedLanes);
479 }
480
481 LLVM_DEBUG({
482 dbgs() << "Defined/Used lanes:\n";
483 for (unsigned RegIdx = 0; RegIdx < NumVirtRegs; ++RegIdx) {
484 Register Reg = Register::index2VirtReg(RegIdx);
485 const VRegInfo &Info = VRegInfos[RegIdx];
486 dbgs() << printReg(Reg, nullptr)
487 << " Used: " << PrintLaneMask(Info.UsedLanes)
488 << " Def: " << PrintLaneMask(Info.DefinedLanes) << '\n';
489 }
490 dbgs() << "\n";
491 });
492}
493
494std::pair<bool, bool>
495DetectDeadLanes::modifySubRegisterOperandStatus(const DeadLaneDetector &DLD,
496 MachineFunction &MF) {
497 bool Changed = false;
498 bool Again = false;
499 // Mark operands as dead/unused.
500 for (MachineBasicBlock &MBB : MF) {
501 for (MachineInstr &MI : MBB) {
502 for (MachineOperand &MO : MI.operands()) {
503 if (!MO.isReg())
504 continue;
505 Register Reg = MO.getReg();
506 if (!Reg.isVirtual())
507 continue;
508 unsigned RegIdx = Reg.virtRegIndex();
509 const DeadLaneDetector::VRegInfo &RegInfo = DLD.getVRegInfo(RegIdx);
510 if (MO.isDef() && !MO.isDead() && RegInfo.UsedLanes.none()) {
511 LLVM_DEBUG(dbgs()
512 << "Marking operand '" << MO << "' as dead in " << MI);
513 MO.setIsDead();
514 Changed = true;
515 }
516 if (MO.readsReg()) {
517 bool CrossCopy = false;
518 if (isUndefRegAtInput(MO, RegInfo)) {
519 LLVM_DEBUG(dbgs()
520 << "Marking operand '" << MO << "' as undef in " << MI);
521 MO.setIsUndef();
522 Changed = true;
523 } else if (isUndefInput(DLD, MO, CrossCopy: &CrossCopy)) {
524 LLVM_DEBUG(dbgs()
525 << "Marking operand '" << MO << "' as undef in " << MI);
526 MO.setIsUndef();
527 Changed = true;
528 if (CrossCopy)
529 Again = true;
530 }
531 }
532 }
533 }
534 }
535
536 return std::make_pair(x&: Changed, y&: Again);
537}
538
539PreservedAnalyses
540DetectDeadLanesPass::run(MachineFunction &MF,
541 MachineFunctionAnalysisManager &MFAM) {
542 if (!DetectDeadLanes().run(MF))
543 return PreservedAnalyses::all();
544 auto PA = getMachineFunctionPassPreservedAnalyses();
545 PA.preserveSet<CFGAnalyses>();
546 return PA;
547}
548
549bool DetectDeadLanes::run(MachineFunction &MF) {
550 // Don't bother if we won't track subregister liveness later. This pass is
551 // required for correctness if subregister liveness is enabled because the
552 // register coalescer cannot deal with hidden dead defs. However without
553 // subregister liveness enabled, the expected benefits of this pass are small
554 // so we safe the compile time.
555 MRI = &MF.getRegInfo();
556 if (!MRI->subRegLivenessEnabled()) {
557 LLVM_DEBUG(dbgs() << "Skipping Detect dead lanes pass\n");
558 return false;
559 }
560
561 TRI = MRI->getTargetRegisterInfo();
562
563 DeadLaneDetector DLD(MRI, TRI);
564
565 bool Changed = false;
566 bool Again;
567 do {
568 DLD.computeSubRegisterLaneBitInfo();
569 bool LocalChanged;
570 std::tie(args&: LocalChanged, args&: Again) = modifySubRegisterOperandStatus(DLD, MF);
571 Changed |= LocalChanged;
572 } while (Again);
573
574 return Changed;
575}
576