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 = *MRI->getVRegDef(Reg);
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 MachineInstr &MODefMI = *MRI->getVRegDef(Reg: MOReg);
301 // Bits from copy-like operations will be added later.
302 if (lowersToCopies(MI: MODefMI) || MODefMI.isImplicitDef())
303 continue;
304 }
305 unsigned MOSubReg = MO.getSubReg();
306 MODefinedLanes = MRI->getMaxLaneMaskForVReg(Reg: MOReg);
307 MODefinedLanes = TRI->reverseComposeSubRegIndexLaneMask(
308 IdxA: MOSubReg, LaneMask: MODefinedLanes);
309 }
310
311 unsigned OpNum = MO.getOperandNo();
312 DefinedLanes |= transferDefinedLanes(Def, OpNum, DefinedLanes: MODefinedLanes);
313 }
314 return DefinedLanes;
315 }
316 if (DefMI.isImplicitDef() || Def.isDead())
317 return LaneBitmask::getNone();
318
319 assert(Def.getSubReg() == 0 &&
320 "Should not have subregister defs in machine SSA phase");
321 return MRI->getMaxLaneMaskForVReg(Reg);
322}
323
324LaneBitmask DeadLaneDetector::determineInitialUsedLanes(Register Reg) {
325 LaneBitmask UsedLanes = LaneBitmask::getNone();
326 for (const MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
327 if (!MO.readsReg())
328 continue;
329
330 const MachineInstr &UseMI = *MO.getParent();
331 if (UseMI.isKill())
332 continue;
333
334 unsigned SubReg = MO.getSubReg();
335 if (lowersToCopies(MI: UseMI)) {
336 assert(UseMI.getDesc().getNumDefs() == 1);
337 const MachineOperand &Def = *UseMI.defs().begin();
338 Register DefReg = Def.getReg();
339 // The used lanes of COPY-like instruction operands are determined by the
340 // following dataflow analysis.
341 if (DefReg.isVirtual()) {
342 // But ignore copies across incompatible register classes.
343 bool CrossCopy = false;
344 if (lowersToCopies(MI: UseMI)) {
345 const TargetRegisterClass *DstRC = MRI->getRegClass(Reg: DefReg);
346 CrossCopy = isCrossCopy(MRI: *MRI, MI: UseMI, DstRC, MO);
347 if (CrossCopy)
348 LLVM_DEBUG(dbgs() << "Copy across incompatible classes: " << UseMI);
349 }
350
351 if (!CrossCopy)
352 continue;
353 }
354 }
355
356 // Shortcut: All lanes are used.
357 if (SubReg == 0)
358 return MRI->getMaxLaneMaskForVReg(Reg);
359
360 UsedLanes |= TRI->getSubRegIndexLaneMask(SubIdx: SubReg);
361 }
362 return UsedLanes;
363}
364
365namespace {
366
367class DetectDeadLanes {
368public:
369 bool run(MachineFunction &MF);
370
371private:
372 /// update the operand status.
373 /// The first return value shows whether MF been changed.
374 /// The second return value indicates we need to call
375 /// DeadLaneDetector::computeSubRegisterLaneBitInfo and this function again
376 /// to propagate changes.
377 std::pair<bool, bool>
378 modifySubRegisterOperandStatus(const DeadLaneDetector &DLD,
379 MachineFunction &MF);
380
381 bool isUndefRegAtInput(const MachineOperand &MO,
382 const DeadLaneDetector::VRegInfo &RegInfo) const;
383
384 bool isUndefInput(const DeadLaneDetector &DLD, const MachineInstr &MI,
385 const MachineOperand &MO, bool *CrossCopy) const;
386
387 const MachineRegisterInfo *MRI = nullptr;
388 const TargetRegisterInfo *TRI = nullptr;
389};
390
391struct DetectDeadLanesLegacy : public MachineFunctionPass {
392 static char ID;
393 DetectDeadLanesLegacy() : MachineFunctionPass(ID) {}
394
395 StringRef getPassName() const override { return "Detect Dead Lanes"; }
396
397 void getAnalysisUsage(AnalysisUsage &AU) const override {
398 AU.setPreservesCFG();
399 MachineFunctionPass::getAnalysisUsage(AU);
400 }
401
402 bool runOnMachineFunction(MachineFunction &MF) override {
403 return DetectDeadLanes().run(MF);
404 }
405};
406
407} // end anonymous namespace
408
409char DetectDeadLanesLegacy::ID = 0;
410char &llvm::DetectDeadLanesID = DetectDeadLanesLegacy::ID;
411
412INITIALIZE_PASS(DetectDeadLanesLegacy, DEBUG_TYPE, "Detect Dead Lanes", false,
413 false)
414
415bool DetectDeadLanes::isUndefRegAtInput(
416 const MachineOperand &MO, const DeadLaneDetector::VRegInfo &RegInfo) const {
417 unsigned SubReg = MO.getSubReg();
418 LaneBitmask Mask = TRI->getSubRegIndexLaneMask(SubIdx: SubReg);
419 return (RegInfo.DefinedLanes & RegInfo.UsedLanes & Mask).none();
420}
421
422bool DetectDeadLanes::isUndefInput(const DeadLaneDetector &DLD,
423 const MachineInstr &MI,
424 const MachineOperand &MO,
425 bool *CrossCopy) const {
426 if (!MO.isUse())
427 return false;
428 if (!lowersToCopies(MI))
429 return false;
430 const MachineOperand &Def = MI.getOperand(i: 0);
431 Register DefReg = Def.getReg();
432 if (!DefReg.isVirtual())
433 return false;
434 unsigned DefRegIdx = DefReg.virtRegIndex();
435 if (!DLD.isDefinedByCopy(RegIdx: DefRegIdx))
436 return false;
437
438 const DeadLaneDetector::VRegInfo &DefRegInfo = DLD.getVRegInfo(RegIdx: DefRegIdx);
439 LaneBitmask UsedLanes = DLD.transferUsedLanes(MI, UsedLanes: DefRegInfo.UsedLanes, MO);
440 if (UsedLanes.any())
441 return false;
442
443 Register MOReg = MO.getReg();
444 if (MOReg.isVirtual()) {
445 const TargetRegisterClass *DstRC = MRI->getRegClass(Reg: DefReg);
446 *CrossCopy = isCrossCopy(MRI: *MRI, MI, DstRC, MO);
447 }
448 return true;
449}
450
451void DeadLaneDetector::computeSubRegisterLaneBitInfo() {
452 // First pass: Populate defs/uses of vregs with initial values
453 unsigned NumVirtRegs = MRI->getNumVirtRegs();
454 for (unsigned RegIdx = 0; RegIdx < NumVirtRegs; ++RegIdx) {
455 Register Reg = Register::index2VirtReg(Index: RegIdx);
456
457 // Determine used/defined lanes and add copy instructions to worklist.
458 VRegInfo &Info = VRegInfos[RegIdx];
459 Info.DefinedLanes = determineInitialDefinedLanes(Reg);
460 Info.UsedLanes = determineInitialUsedLanes(Reg);
461 }
462
463 // Iterate as long as defined lanes/used lanes keep changing.
464 while (!Worklist.empty()) {
465 unsigned RegIdx = Worklist.front();
466 Worklist.pop_front();
467 WorklistMembers.reset(Idx: RegIdx);
468 VRegInfo &Info = VRegInfos[RegIdx];
469 Register Reg = Register::index2VirtReg(Index: RegIdx);
470
471 // Transfer UsedLanes to operands of DefMI (backwards dataflow).
472 const MachineInstr &MI = *MRI->getVRegDef(Reg);
473 transferUsedLanesStep(MI, UsedLanes: Info.UsedLanes);
474 // Transfer DefinedLanes to users of Reg (forward dataflow).
475 for (const MachineOperand &MO : MRI->use_nodbg_operands(Reg))
476 transferDefinedLanesStep(Use: MO, DefinedLanes: Info.DefinedLanes);
477 }
478
479 LLVM_DEBUG({
480 dbgs() << "Defined/Used lanes:\n";
481 for (unsigned RegIdx = 0; RegIdx < NumVirtRegs; ++RegIdx) {
482 Register Reg = Register::index2VirtReg(RegIdx);
483 const VRegInfo &Info = VRegInfos[RegIdx];
484 dbgs() << printReg(Reg, nullptr)
485 << " Used: " << PrintLaneMask(Info.UsedLanes)
486 << " Def: " << PrintLaneMask(Info.DefinedLanes) << '\n';
487 }
488 dbgs() << "\n";
489 });
490}
491
492std::pair<bool, bool>
493DetectDeadLanes::modifySubRegisterOperandStatus(const DeadLaneDetector &DLD,
494 MachineFunction &MF) {
495 bool Changed = false;
496 bool Again = false;
497 // Mark operands as dead/unused.
498 for (MachineBasicBlock &MBB : MF) {
499 for (MachineInstr &MI : MBB) {
500 for (MachineOperand &MO : MI.operands()) {
501 if (!MO.isReg())
502 continue;
503 Register Reg = MO.getReg();
504 if (!Reg.isVirtual())
505 continue;
506 unsigned RegIdx = Reg.virtRegIndex();
507 const DeadLaneDetector::VRegInfo &RegInfo = DLD.getVRegInfo(RegIdx);
508 if (MO.isDef() && !MO.isDead() && RegInfo.UsedLanes.none()) {
509 LLVM_DEBUG(dbgs()
510 << "Marking operand '" << MO << "' as dead in " << MI);
511 MO.setIsDead();
512 Changed = true;
513 }
514 if (MO.readsReg()) {
515 bool CrossCopy = false;
516 if (isUndefRegAtInput(MO, RegInfo)) {
517 LLVM_DEBUG(dbgs()
518 << "Marking operand '" << MO << "' as undef in " << MI);
519 MO.setIsUndef();
520 Changed = true;
521 } else if (isUndefInput(DLD, MI, MO, CrossCopy: &CrossCopy)) {
522 LLVM_DEBUG(dbgs()
523 << "Marking operand '" << MO << "' as undef in " << MI);
524 MO.setIsUndef();
525 Changed = true;
526 if (CrossCopy)
527 Again = true;
528 }
529 }
530 }
531 }
532 }
533
534 return std::make_pair(x&: Changed, y&: Again);
535}
536
537PreservedAnalyses
538DetectDeadLanesPass::run(MachineFunction &MF,
539 MachineFunctionAnalysisManager &MFAM) {
540 if (!DetectDeadLanes().run(MF))
541 return PreservedAnalyses::all();
542 auto PA = getMachineFunctionPassPreservedAnalyses();
543 PA.preserveSet<CFGAnalyses>();
544 return PA;
545}
546
547bool DetectDeadLanes::run(MachineFunction &MF) {
548 // Don't bother if we won't track subregister liveness later. This pass is
549 // required for correctness if subregister liveness is enabled because the
550 // register coalescer cannot deal with hidden dead defs. However without
551 // subregister liveness enabled, the expected benefits of this pass are small
552 // so we safe the compile time.
553 MRI = &MF.getRegInfo();
554 if (!MRI->subRegLivenessEnabled()) {
555 LLVM_DEBUG(dbgs() << "Skipping Detect dead lanes pass\n");
556 return false;
557 }
558
559 TRI = MRI->getTargetRegisterInfo();
560
561 DeadLaneDetector DLD(MRI, TRI);
562
563 bool Changed = false;
564 bool Again;
565 do {
566 DLD.computeSubRegisterLaneBitInfo();
567 bool LocalChanged;
568 std::tie(args&: LocalChanged, args&: Again) = modifySubRegisterOperandStatus(DLD, MF);
569 Changed |= LocalChanged;
570 } while (Again);
571
572 return Changed;
573}
574