xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/DetectDeadLanes.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===- DetectDeadLanes.cpp - SubRegister Lane Usage Analysis --*- C++ -*---===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// Analysis that tracks defined/used subregister lanes across COPY instructions
110b57cec5SDimitry Andric /// and instructions that get lowered to a COPY (PHI, REG_SEQUENCE,
120b57cec5SDimitry Andric /// INSERT_SUBREG, EXTRACT_SUBREG).
130b57cec5SDimitry Andric /// The information is used to detect dead definitions and the usage of
140b57cec5SDimitry Andric /// (completely) undefined values and mark the operands as such.
150b57cec5SDimitry Andric /// This pass is necessary because the dead/undef status is not obvious anymore
160b57cec5SDimitry Andric /// when subregisters are involved.
170b57cec5SDimitry Andric ///
180b57cec5SDimitry Andric /// Example:
190b57cec5SDimitry Andric ///    %0 = some definition
200b57cec5SDimitry Andric ///    %1 = IMPLICIT_DEF
210b57cec5SDimitry Andric ///    %2 = REG_SEQUENCE %0, sub0, %1, sub1
220b57cec5SDimitry Andric ///    %3 = EXTRACT_SUBREG %2, sub1
230b57cec5SDimitry Andric ///       = use %3
240b57cec5SDimitry Andric /// The %0 definition is dead and %3 contains an undefined value.
250b57cec5SDimitry Andric //
260b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
270b57cec5SDimitry Andric 
28*06c3fb27SDimitry Andric #include "llvm/CodeGen/DetectDeadLanes.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
320b57cec5SDimitry Andric #include "llvm/InitializePasses.h"
330b57cec5SDimitry Andric #include "llvm/Pass.h"
340b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
350b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric using namespace llvm;
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric #define DEBUG_TYPE "detect-dead-lanes"
400b57cec5SDimitry Andric 
DeadLaneDetector(const MachineRegisterInfo * MRI,const TargetRegisterInfo * TRI)41*06c3fb27SDimitry Andric DeadLaneDetector::DeadLaneDetector(const MachineRegisterInfo *MRI,
42*06c3fb27SDimitry Andric                                    const TargetRegisterInfo *TRI)
43*06c3fb27SDimitry Andric     : MRI(MRI), TRI(TRI) {
44*06c3fb27SDimitry Andric   unsigned NumVirtRegs = MRI->getNumVirtRegs();
45*06c3fb27SDimitry Andric   VRegInfos = std::unique_ptr<VRegInfo[]>(new VRegInfo[NumVirtRegs]);
46*06c3fb27SDimitry Andric   WorklistMembers.resize(NumVirtRegs);
47*06c3fb27SDimitry Andric   DefinedByCopy.resize(NumVirtRegs);
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric /// Returns true if \p MI will get lowered to a series of COPY instructions.
510b57cec5SDimitry Andric /// We call this a COPY-like instruction.
lowersToCopies(const MachineInstr & MI)520b57cec5SDimitry Andric static bool lowersToCopies(const MachineInstr &MI) {
530b57cec5SDimitry Andric   // Note: We could support instructions with MCInstrDesc::isRegSequenceLike(),
540b57cec5SDimitry Andric   // isExtractSubRegLike(), isInsertSubregLike() in the future even though they
550b57cec5SDimitry Andric   // are not lowered to a COPY.
560b57cec5SDimitry Andric   switch (MI.getOpcode()) {
570b57cec5SDimitry Andric   case TargetOpcode::COPY:
580b57cec5SDimitry Andric   case TargetOpcode::PHI:
590b57cec5SDimitry Andric   case TargetOpcode::INSERT_SUBREG:
600b57cec5SDimitry Andric   case TargetOpcode::REG_SEQUENCE:
610b57cec5SDimitry Andric   case TargetOpcode::EXTRACT_SUBREG:
620b57cec5SDimitry Andric     return true;
630b57cec5SDimitry Andric   }
640b57cec5SDimitry Andric   return false;
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
isCrossCopy(const MachineRegisterInfo & MRI,const MachineInstr & MI,const TargetRegisterClass * DstRC,const MachineOperand & MO)670b57cec5SDimitry Andric static bool isCrossCopy(const MachineRegisterInfo &MRI,
680b57cec5SDimitry Andric                         const MachineInstr &MI,
690b57cec5SDimitry Andric                         const TargetRegisterClass *DstRC,
700b57cec5SDimitry Andric                         const MachineOperand &MO) {
710b57cec5SDimitry Andric   assert(lowersToCopies(MI));
728bcb0991SDimitry Andric   Register SrcReg = MO.getReg();
730b57cec5SDimitry Andric   const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
740b57cec5SDimitry Andric   if (DstRC == SrcRC)
750b57cec5SDimitry Andric     return false;
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   unsigned SrcSubIdx = MO.getSubReg();
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
800b57cec5SDimitry Andric   unsigned DstSubIdx = 0;
810b57cec5SDimitry Andric   switch (MI.getOpcode()) {
820b57cec5SDimitry Andric   case TargetOpcode::INSERT_SUBREG:
83*06c3fb27SDimitry Andric     if (MO.getOperandNo() == 2)
840b57cec5SDimitry Andric       DstSubIdx = MI.getOperand(3).getImm();
850b57cec5SDimitry Andric     break;
860b57cec5SDimitry Andric   case TargetOpcode::REG_SEQUENCE: {
87*06c3fb27SDimitry Andric     unsigned OpNum = MO.getOperandNo();
880b57cec5SDimitry Andric     DstSubIdx = MI.getOperand(OpNum+1).getImm();
890b57cec5SDimitry Andric     break;
900b57cec5SDimitry Andric   }
910b57cec5SDimitry Andric   case TargetOpcode::EXTRACT_SUBREG: {
920b57cec5SDimitry Andric     unsigned SubReg = MI.getOperand(2).getImm();
930b57cec5SDimitry Andric     SrcSubIdx = TRI.composeSubRegIndices(SubReg, SrcSubIdx);
940b57cec5SDimitry Andric   }
950b57cec5SDimitry Andric   }
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   unsigned PreA, PreB; // Unused.
980b57cec5SDimitry Andric   if (SrcSubIdx && DstSubIdx)
990b57cec5SDimitry Andric     return !TRI.getCommonSuperRegClass(SrcRC, SrcSubIdx, DstRC, DstSubIdx, PreA,
1000b57cec5SDimitry Andric                                        PreB);
1010b57cec5SDimitry Andric   if (SrcSubIdx)
1020b57cec5SDimitry Andric     return !TRI.getMatchingSuperRegClass(SrcRC, DstRC, SrcSubIdx);
1030b57cec5SDimitry Andric   if (DstSubIdx)
1040b57cec5SDimitry Andric     return !TRI.getMatchingSuperRegClass(DstRC, SrcRC, DstSubIdx);
1050b57cec5SDimitry Andric   return !TRI.getCommonSubClass(SrcRC, DstRC);
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric 
addUsedLanesOnOperand(const MachineOperand & MO,LaneBitmask UsedLanes)108*06c3fb27SDimitry Andric void DeadLaneDetector::addUsedLanesOnOperand(const MachineOperand &MO,
1090b57cec5SDimitry Andric                                              LaneBitmask UsedLanes) {
1100b57cec5SDimitry Andric   if (!MO.readsReg())
1110b57cec5SDimitry Andric     return;
1128bcb0991SDimitry Andric   Register MOReg = MO.getReg();
113bdd1243dSDimitry Andric   if (!MOReg.isVirtual())
1140b57cec5SDimitry Andric     return;
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   unsigned MOSubReg = MO.getSubReg();
1170b57cec5SDimitry Andric   if (MOSubReg != 0)
1180b57cec5SDimitry Andric     UsedLanes = TRI->composeSubRegIndexLaneMask(MOSubReg, UsedLanes);
1190b57cec5SDimitry Andric   UsedLanes &= MRI->getMaxLaneMaskForVReg(MOReg);
1200b57cec5SDimitry Andric 
1218bcb0991SDimitry Andric   unsigned MORegIdx = Register::virtReg2Index(MOReg);
122*06c3fb27SDimitry Andric   DeadLaneDetector::VRegInfo &MORegInfo = VRegInfos[MORegIdx];
1230b57cec5SDimitry Andric   LaneBitmask PrevUsedLanes = MORegInfo.UsedLanes;
1240b57cec5SDimitry Andric   // Any change at all?
1250b57cec5SDimitry Andric   if ((UsedLanes & ~PrevUsedLanes).none())
1260b57cec5SDimitry Andric     return;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   // Set UsedLanes and remember instruction for further propagation.
1290b57cec5SDimitry Andric   MORegInfo.UsedLanes = PrevUsedLanes | UsedLanes;
1300b57cec5SDimitry Andric   if (DefinedByCopy.test(MORegIdx))
1310b57cec5SDimitry Andric     PutInWorklist(MORegIdx);
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
transferUsedLanesStep(const MachineInstr & MI,LaneBitmask UsedLanes)134*06c3fb27SDimitry Andric void DeadLaneDetector::transferUsedLanesStep(const MachineInstr &MI,
1350b57cec5SDimitry Andric                                              LaneBitmask UsedLanes) {
1360b57cec5SDimitry Andric   for (const MachineOperand &MO : MI.uses()) {
137bdd1243dSDimitry Andric     if (!MO.isReg() || !MO.getReg().isVirtual())
1380b57cec5SDimitry Andric       continue;
1390b57cec5SDimitry Andric     LaneBitmask UsedOnMO = transferUsedLanes(MI, UsedLanes, MO);
1400b57cec5SDimitry Andric     addUsedLanesOnOperand(MO, UsedOnMO);
1410b57cec5SDimitry Andric   }
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
144*06c3fb27SDimitry Andric LaneBitmask
transferUsedLanes(const MachineInstr & MI,LaneBitmask UsedLanes,const MachineOperand & MO) const145*06c3fb27SDimitry Andric DeadLaneDetector::transferUsedLanes(const MachineInstr &MI,
1460b57cec5SDimitry Andric                                     LaneBitmask UsedLanes,
1470b57cec5SDimitry Andric                                     const MachineOperand &MO) const {
148*06c3fb27SDimitry Andric   unsigned OpNum = MO.getOperandNo();
1498bcb0991SDimitry Andric   assert(lowersToCopies(MI) &&
1508bcb0991SDimitry Andric          DefinedByCopy[Register::virtReg2Index(MI.getOperand(0).getReg())]);
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   switch (MI.getOpcode()) {
1530b57cec5SDimitry Andric   case TargetOpcode::COPY:
1540b57cec5SDimitry Andric   case TargetOpcode::PHI:
1550b57cec5SDimitry Andric     return UsedLanes;
1560b57cec5SDimitry Andric   case TargetOpcode::REG_SEQUENCE: {
1570b57cec5SDimitry Andric     assert(OpNum % 2 == 1);
1580b57cec5SDimitry Andric     unsigned SubIdx = MI.getOperand(OpNum + 1).getImm();
1590b57cec5SDimitry Andric     return TRI->reverseComposeSubRegIndexLaneMask(SubIdx, UsedLanes);
1600b57cec5SDimitry Andric   }
1610b57cec5SDimitry Andric   case TargetOpcode::INSERT_SUBREG: {
1620b57cec5SDimitry Andric     unsigned SubIdx = MI.getOperand(3).getImm();
1630b57cec5SDimitry Andric     LaneBitmask MO2UsedLanes =
1640b57cec5SDimitry Andric         TRI->reverseComposeSubRegIndexLaneMask(SubIdx, UsedLanes);
1650b57cec5SDimitry Andric     if (OpNum == 2)
1660b57cec5SDimitry Andric       return MO2UsedLanes;
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric     const MachineOperand &Def = MI.getOperand(0);
1698bcb0991SDimitry Andric     Register DefReg = Def.getReg();
1700b57cec5SDimitry Andric     const TargetRegisterClass *RC = MRI->getRegClass(DefReg);
1710b57cec5SDimitry Andric     LaneBitmask MO1UsedLanes;
1720b57cec5SDimitry Andric     if (RC->CoveredBySubRegs)
1730b57cec5SDimitry Andric       MO1UsedLanes = UsedLanes & ~TRI->getSubRegIndexLaneMask(SubIdx);
1740b57cec5SDimitry Andric     else
1750b57cec5SDimitry Andric       MO1UsedLanes = RC->LaneMask;
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric     assert(OpNum == 1);
1780b57cec5SDimitry Andric     return MO1UsedLanes;
1790b57cec5SDimitry Andric   }
1800b57cec5SDimitry Andric   case TargetOpcode::EXTRACT_SUBREG: {
1810b57cec5SDimitry Andric     assert(OpNum == 1);
1820b57cec5SDimitry Andric     unsigned SubIdx = MI.getOperand(2).getImm();
1830b57cec5SDimitry Andric     return TRI->composeSubRegIndexLaneMask(SubIdx, UsedLanes);
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric   default:
1860b57cec5SDimitry Andric     llvm_unreachable("function must be called with COPY-like instruction");
1870b57cec5SDimitry Andric   }
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
transferDefinedLanesStep(const MachineOperand & Use,LaneBitmask DefinedLanes)190*06c3fb27SDimitry Andric void DeadLaneDetector::transferDefinedLanesStep(const MachineOperand &Use,
1910b57cec5SDimitry Andric                                                 LaneBitmask DefinedLanes) {
1920b57cec5SDimitry Andric   if (!Use.readsReg())
1930b57cec5SDimitry Andric     return;
1940b57cec5SDimitry Andric   // Check whether the operand writes a vreg and is part of a COPY-like
1950b57cec5SDimitry Andric   // instruction.
1960b57cec5SDimitry Andric   const MachineInstr &MI = *Use.getParent();
1970b57cec5SDimitry Andric   if (MI.getDesc().getNumDefs() != 1)
1980b57cec5SDimitry Andric     return;
1990b57cec5SDimitry Andric   // FIXME: PATCHPOINT instructions announce a Def that does not always exist,
2000b57cec5SDimitry Andric   // they really need to be modeled differently!
2010b57cec5SDimitry Andric   if (MI.getOpcode() == TargetOpcode::PATCHPOINT)
2020b57cec5SDimitry Andric     return;
2030b57cec5SDimitry Andric   const MachineOperand &Def = *MI.defs().begin();
2048bcb0991SDimitry Andric   Register DefReg = Def.getReg();
205bdd1243dSDimitry Andric   if (!DefReg.isVirtual())
2060b57cec5SDimitry Andric     return;
2078bcb0991SDimitry Andric   unsigned DefRegIdx = Register::virtReg2Index(DefReg);
2080b57cec5SDimitry Andric   if (!DefinedByCopy.test(DefRegIdx))
2090b57cec5SDimitry Andric     return;
2100b57cec5SDimitry Andric 
211*06c3fb27SDimitry Andric   unsigned OpNum = Use.getOperandNo();
2120b57cec5SDimitry Andric   DefinedLanes =
2130b57cec5SDimitry Andric       TRI->reverseComposeSubRegIndexLaneMask(Use.getSubReg(), DefinedLanes);
2140b57cec5SDimitry Andric   DefinedLanes = transferDefinedLanes(Def, OpNum, DefinedLanes);
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   VRegInfo &RegInfo = VRegInfos[DefRegIdx];
2170b57cec5SDimitry Andric   LaneBitmask PrevDefinedLanes = RegInfo.DefinedLanes;
2180b57cec5SDimitry Andric   // Any change at all?
2190b57cec5SDimitry Andric   if ((DefinedLanes & ~PrevDefinedLanes).none())
2200b57cec5SDimitry Andric     return;
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   RegInfo.DefinedLanes = PrevDefinedLanes | DefinedLanes;
2230b57cec5SDimitry Andric   PutInWorklist(DefRegIdx);
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric 
transferDefinedLanes(const MachineOperand & Def,unsigned OpNum,LaneBitmask DefinedLanes) const226*06c3fb27SDimitry Andric LaneBitmask DeadLaneDetector::transferDefinedLanes(
227*06c3fb27SDimitry Andric     const MachineOperand &Def, unsigned OpNum, LaneBitmask DefinedLanes) const {
2280b57cec5SDimitry Andric   const MachineInstr &MI = *Def.getParent();
2290b57cec5SDimitry Andric   // Translate DefinedLanes if necessary.
2300b57cec5SDimitry Andric   switch (MI.getOpcode()) {
2310b57cec5SDimitry Andric   case TargetOpcode::REG_SEQUENCE: {
2320b57cec5SDimitry Andric     unsigned SubIdx = MI.getOperand(OpNum + 1).getImm();
2330b57cec5SDimitry Andric     DefinedLanes = TRI->composeSubRegIndexLaneMask(SubIdx, DefinedLanes);
2340b57cec5SDimitry Andric     DefinedLanes &= TRI->getSubRegIndexLaneMask(SubIdx);
2350b57cec5SDimitry Andric     break;
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric   case TargetOpcode::INSERT_SUBREG: {
2380b57cec5SDimitry Andric     unsigned SubIdx = MI.getOperand(3).getImm();
2390b57cec5SDimitry Andric     if (OpNum == 2) {
2400b57cec5SDimitry Andric       DefinedLanes = TRI->composeSubRegIndexLaneMask(SubIdx, DefinedLanes);
2410b57cec5SDimitry Andric       DefinedLanes &= TRI->getSubRegIndexLaneMask(SubIdx);
2420b57cec5SDimitry Andric     } else {
2430b57cec5SDimitry Andric       assert(OpNum == 1 && "INSERT_SUBREG must have two operands");
2440b57cec5SDimitry Andric       // Ignore lanes defined by operand 2.
2450b57cec5SDimitry Andric       DefinedLanes &= ~TRI->getSubRegIndexLaneMask(SubIdx);
2460b57cec5SDimitry Andric     }
2470b57cec5SDimitry Andric     break;
2480b57cec5SDimitry Andric   }
2490b57cec5SDimitry Andric   case TargetOpcode::EXTRACT_SUBREG: {
2500b57cec5SDimitry Andric     unsigned SubIdx = MI.getOperand(2).getImm();
2510b57cec5SDimitry Andric     assert(OpNum == 1 && "EXTRACT_SUBREG must have one register operand only");
2520b57cec5SDimitry Andric     DefinedLanes = TRI->reverseComposeSubRegIndexLaneMask(SubIdx, DefinedLanes);
2530b57cec5SDimitry Andric     break;
2540b57cec5SDimitry Andric   }
2550b57cec5SDimitry Andric   case TargetOpcode::COPY:
2560b57cec5SDimitry Andric   case TargetOpcode::PHI:
2570b57cec5SDimitry Andric     break;
2580b57cec5SDimitry Andric   default:
2590b57cec5SDimitry Andric     llvm_unreachable("function must be called with COPY-like instruction");
2600b57cec5SDimitry Andric   }
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   assert(Def.getSubReg() == 0 &&
2630b57cec5SDimitry Andric          "Should not have subregister defs in machine SSA phase");
2640b57cec5SDimitry Andric   DefinedLanes &= MRI->getMaxLaneMaskForVReg(Def.getReg());
2650b57cec5SDimitry Andric   return DefinedLanes;
2660b57cec5SDimitry Andric }
2670b57cec5SDimitry Andric 
determineInitialDefinedLanes(unsigned Reg)268*06c3fb27SDimitry Andric LaneBitmask DeadLaneDetector::determineInitialDefinedLanes(unsigned Reg) {
2690b57cec5SDimitry Andric   // Live-In or unused registers have no definition but are considered fully
2700b57cec5SDimitry Andric   // defined.
2710b57cec5SDimitry Andric   if (!MRI->hasOneDef(Reg))
2720b57cec5SDimitry Andric     return LaneBitmask::getAll();
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   const MachineOperand &Def = *MRI->def_begin(Reg);
2750b57cec5SDimitry Andric   const MachineInstr &DefMI = *Def.getParent();
2760b57cec5SDimitry Andric   if (lowersToCopies(DefMI)) {
2770b57cec5SDimitry Andric     // Start optimisatically with no used or defined lanes for copy
2780b57cec5SDimitry Andric     // instructions. The following dataflow analysis will add more bits.
2798bcb0991SDimitry Andric     unsigned RegIdx = Register::virtReg2Index(Reg);
2800b57cec5SDimitry Andric     DefinedByCopy.set(RegIdx);
2810b57cec5SDimitry Andric     PutInWorklist(RegIdx);
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric     if (Def.isDead())
2840b57cec5SDimitry Andric       return LaneBitmask::getNone();
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric     // COPY/PHI can copy across unrelated register classes (example: float/int)
2870b57cec5SDimitry Andric     // with incompatible subregister structure. Do not include these in the
2880b57cec5SDimitry Andric     // dataflow analysis since we cannot transfer lanemasks in a meaningful way.
2890b57cec5SDimitry Andric     const TargetRegisterClass *DefRC = MRI->getRegClass(Reg);
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric     // Determine initially DefinedLanes.
2920b57cec5SDimitry Andric     LaneBitmask DefinedLanes;
2930b57cec5SDimitry Andric     for (const MachineOperand &MO : DefMI.uses()) {
2940b57cec5SDimitry Andric       if (!MO.isReg() || !MO.readsReg())
2950b57cec5SDimitry Andric         continue;
2968bcb0991SDimitry Andric       Register MOReg = MO.getReg();
2970b57cec5SDimitry Andric       if (!MOReg)
2980b57cec5SDimitry Andric         continue;
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric       LaneBitmask MODefinedLanes;
301bdd1243dSDimitry Andric       if (MOReg.isPhysical()) {
3020b57cec5SDimitry Andric         MODefinedLanes = LaneBitmask::getAll();
3030b57cec5SDimitry Andric       } else if (isCrossCopy(*MRI, DefMI, DefRC, MO)) {
3040b57cec5SDimitry Andric         MODefinedLanes = LaneBitmask::getAll();
3050b57cec5SDimitry Andric       } else {
306bdd1243dSDimitry Andric         assert(MOReg.isVirtual());
3070b57cec5SDimitry Andric         if (MRI->hasOneDef(MOReg)) {
3080b57cec5SDimitry Andric           const MachineOperand &MODef = *MRI->def_begin(MOReg);
3090b57cec5SDimitry Andric           const MachineInstr &MODefMI = *MODef.getParent();
3100b57cec5SDimitry Andric           // Bits from copy-like operations will be added later.
3110b57cec5SDimitry Andric           if (lowersToCopies(MODefMI) || MODefMI.isImplicitDef())
3120b57cec5SDimitry Andric             continue;
3130b57cec5SDimitry Andric         }
3140b57cec5SDimitry Andric         unsigned MOSubReg = MO.getSubReg();
3150b57cec5SDimitry Andric         MODefinedLanes = MRI->getMaxLaneMaskForVReg(MOReg);
3160b57cec5SDimitry Andric         MODefinedLanes = TRI->reverseComposeSubRegIndexLaneMask(
3170b57cec5SDimitry Andric             MOSubReg, MODefinedLanes);
3180b57cec5SDimitry Andric       }
3190b57cec5SDimitry Andric 
320*06c3fb27SDimitry Andric       unsigned OpNum = MO.getOperandNo();
3210b57cec5SDimitry Andric       DefinedLanes |= transferDefinedLanes(Def, OpNum, MODefinedLanes);
3220b57cec5SDimitry Andric     }
3230b57cec5SDimitry Andric     return DefinedLanes;
3240b57cec5SDimitry Andric   }
3250b57cec5SDimitry Andric   if (DefMI.isImplicitDef() || Def.isDead())
3260b57cec5SDimitry Andric     return LaneBitmask::getNone();
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric   assert(Def.getSubReg() == 0 &&
3290b57cec5SDimitry Andric          "Should not have subregister defs in machine SSA phase");
3300b57cec5SDimitry Andric   return MRI->getMaxLaneMaskForVReg(Reg);
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric 
determineInitialUsedLanes(unsigned Reg)333*06c3fb27SDimitry Andric LaneBitmask DeadLaneDetector::determineInitialUsedLanes(unsigned Reg) {
3340b57cec5SDimitry Andric   LaneBitmask UsedLanes = LaneBitmask::getNone();
3350b57cec5SDimitry Andric   for (const MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
3360b57cec5SDimitry Andric     if (!MO.readsReg())
3370b57cec5SDimitry Andric       continue;
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric     const MachineInstr &UseMI = *MO.getParent();
3400b57cec5SDimitry Andric     if (UseMI.isKill())
3410b57cec5SDimitry Andric       continue;
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric     unsigned SubReg = MO.getSubReg();
3440b57cec5SDimitry Andric     if (lowersToCopies(UseMI)) {
3450b57cec5SDimitry Andric       assert(UseMI.getDesc().getNumDefs() == 1);
3460b57cec5SDimitry Andric       const MachineOperand &Def = *UseMI.defs().begin();
3478bcb0991SDimitry Andric       Register DefReg = Def.getReg();
3480b57cec5SDimitry Andric       // The used lanes of COPY-like instruction operands are determined by the
3490b57cec5SDimitry Andric       // following dataflow analysis.
350bdd1243dSDimitry Andric       if (DefReg.isVirtual()) {
3510b57cec5SDimitry Andric         // But ignore copies across incompatible register classes.
3520b57cec5SDimitry Andric         bool CrossCopy = false;
3530b57cec5SDimitry Andric         if (lowersToCopies(UseMI)) {
3540b57cec5SDimitry Andric           const TargetRegisterClass *DstRC = MRI->getRegClass(DefReg);
3550b57cec5SDimitry Andric           CrossCopy = isCrossCopy(*MRI, UseMI, DstRC, MO);
3560b57cec5SDimitry Andric           if (CrossCopy)
3570b57cec5SDimitry Andric             LLVM_DEBUG(dbgs() << "Copy across incompatible classes: " << UseMI);
3580b57cec5SDimitry Andric         }
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric         if (!CrossCopy)
3610b57cec5SDimitry Andric           continue;
3620b57cec5SDimitry Andric       }
3630b57cec5SDimitry Andric     }
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric     // Shortcut: All lanes are used.
3660b57cec5SDimitry Andric     if (SubReg == 0)
3670b57cec5SDimitry Andric       return MRI->getMaxLaneMaskForVReg(Reg);
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric     UsedLanes |= TRI->getSubRegIndexLaneMask(SubReg);
3700b57cec5SDimitry Andric   }
3710b57cec5SDimitry Andric   return UsedLanes;
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric 
374*06c3fb27SDimitry Andric namespace {
375*06c3fb27SDimitry Andric 
376*06c3fb27SDimitry Andric class DetectDeadLanes : public MachineFunctionPass {
377*06c3fb27SDimitry Andric public:
378*06c3fb27SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
379*06c3fb27SDimitry Andric 
380*06c3fb27SDimitry Andric   static char ID;
DetectDeadLanes()381*06c3fb27SDimitry Andric   DetectDeadLanes() : MachineFunctionPass(ID) {}
382*06c3fb27SDimitry Andric 
getPassName() const383*06c3fb27SDimitry Andric   StringRef getPassName() const override { return "Detect Dead Lanes"; }
384*06c3fb27SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const385*06c3fb27SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
386*06c3fb27SDimitry Andric     AU.setPreservesCFG();
387*06c3fb27SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
388*06c3fb27SDimitry Andric   }
389*06c3fb27SDimitry Andric 
390*06c3fb27SDimitry Andric private:
391*06c3fb27SDimitry Andric   /// update the operand status.
392*06c3fb27SDimitry Andric   /// The first return value shows whether MF been changed.
393*06c3fb27SDimitry Andric   /// The second return value indicates we need to call
394*06c3fb27SDimitry Andric   /// DeadLaneDetector::computeSubRegisterLaneBitInfo and this function again
395*06c3fb27SDimitry Andric   /// to propagate changes.
396*06c3fb27SDimitry Andric   std::pair<bool, bool>
397*06c3fb27SDimitry Andric   modifySubRegisterOperandStatus(const DeadLaneDetector &DLD,
398*06c3fb27SDimitry Andric                                  MachineFunction &MF);
399*06c3fb27SDimitry Andric 
400*06c3fb27SDimitry Andric   bool isUndefRegAtInput(const MachineOperand &MO,
401*06c3fb27SDimitry Andric                          const DeadLaneDetector::VRegInfo &RegInfo) const;
402*06c3fb27SDimitry Andric 
403*06c3fb27SDimitry Andric   bool isUndefInput(const DeadLaneDetector &DLD, const MachineOperand &MO,
404*06c3fb27SDimitry Andric                     bool *CrossCopy) const;
405*06c3fb27SDimitry Andric 
406*06c3fb27SDimitry Andric   const MachineRegisterInfo *MRI = nullptr;
407*06c3fb27SDimitry Andric   const TargetRegisterInfo *TRI = nullptr;
408*06c3fb27SDimitry Andric };
409*06c3fb27SDimitry Andric 
410*06c3fb27SDimitry Andric } // end anonymous namespace
411*06c3fb27SDimitry Andric 
412*06c3fb27SDimitry Andric char DetectDeadLanes::ID = 0;
413*06c3fb27SDimitry Andric char &llvm::DetectDeadLanesID = DetectDeadLanes::ID;
414*06c3fb27SDimitry Andric 
415*06c3fb27SDimitry Andric INITIALIZE_PASS(DetectDeadLanes, DEBUG_TYPE, "Detect Dead Lanes", false, false)
416*06c3fb27SDimitry Andric 
isUndefRegAtInput(const MachineOperand & MO,const DeadLaneDetector::VRegInfo & RegInfo) const417*06c3fb27SDimitry Andric bool DetectDeadLanes::isUndefRegAtInput(
418*06c3fb27SDimitry Andric     const MachineOperand &MO, const DeadLaneDetector::VRegInfo &RegInfo) const {
4190b57cec5SDimitry Andric   unsigned SubReg = MO.getSubReg();
4200b57cec5SDimitry Andric   LaneBitmask Mask = TRI->getSubRegIndexLaneMask(SubReg);
4210b57cec5SDimitry Andric   return (RegInfo.DefinedLanes & RegInfo.UsedLanes & Mask).none();
4220b57cec5SDimitry Andric }
4230b57cec5SDimitry Andric 
isUndefInput(const DeadLaneDetector & DLD,const MachineOperand & MO,bool * CrossCopy) const424*06c3fb27SDimitry Andric bool DetectDeadLanes::isUndefInput(const DeadLaneDetector &DLD,
425*06c3fb27SDimitry Andric                                    const MachineOperand &MO,
4260b57cec5SDimitry Andric                                    bool *CrossCopy) const {
4270b57cec5SDimitry Andric   if (!MO.isUse())
4280b57cec5SDimitry Andric     return false;
4290b57cec5SDimitry Andric   const MachineInstr &MI = *MO.getParent();
4300b57cec5SDimitry Andric   if (!lowersToCopies(MI))
4310b57cec5SDimitry Andric     return false;
4320b57cec5SDimitry Andric   const MachineOperand &Def = MI.getOperand(0);
4338bcb0991SDimitry Andric   Register DefReg = Def.getReg();
434bdd1243dSDimitry Andric   if (!DefReg.isVirtual())
4350b57cec5SDimitry Andric     return false;
4368bcb0991SDimitry Andric   unsigned DefRegIdx = Register::virtReg2Index(DefReg);
437*06c3fb27SDimitry Andric   if (!DLD.isDefinedByCopy(DefRegIdx))
4380b57cec5SDimitry Andric     return false;
4390b57cec5SDimitry Andric 
440*06c3fb27SDimitry Andric   const DeadLaneDetector::VRegInfo &DefRegInfo = DLD.getVRegInfo(DefRegIdx);
441*06c3fb27SDimitry Andric   LaneBitmask UsedLanes = DLD.transferUsedLanes(MI, DefRegInfo.UsedLanes, MO);
4420b57cec5SDimitry Andric   if (UsedLanes.any())
4430b57cec5SDimitry Andric     return false;
4440b57cec5SDimitry Andric 
4458bcb0991SDimitry Andric   Register MOReg = MO.getReg();
446bdd1243dSDimitry Andric   if (MOReg.isVirtual()) {
4470b57cec5SDimitry Andric     const TargetRegisterClass *DstRC = MRI->getRegClass(DefReg);
4480b57cec5SDimitry Andric     *CrossCopy = isCrossCopy(*MRI, MI, DstRC, MO);
4490b57cec5SDimitry Andric   }
4500b57cec5SDimitry Andric   return true;
4510b57cec5SDimitry Andric }
4520b57cec5SDimitry Andric 
computeSubRegisterLaneBitInfo()453*06c3fb27SDimitry Andric void DeadLaneDetector::computeSubRegisterLaneBitInfo() {
4540b57cec5SDimitry Andric   // First pass: Populate defs/uses of vregs with initial values
4550b57cec5SDimitry Andric   unsigned NumVirtRegs = MRI->getNumVirtRegs();
4560b57cec5SDimitry Andric   for (unsigned RegIdx = 0; RegIdx < NumVirtRegs; ++RegIdx) {
457bdd1243dSDimitry Andric     Register Reg = Register::index2VirtReg(RegIdx);
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric     // Determine used/defined lanes and add copy instructions to worklist.
4600b57cec5SDimitry Andric     VRegInfo &Info = VRegInfos[RegIdx];
4610b57cec5SDimitry Andric     Info.DefinedLanes = determineInitialDefinedLanes(Reg);
4620b57cec5SDimitry Andric     Info.UsedLanes = determineInitialUsedLanes(Reg);
4630b57cec5SDimitry Andric   }
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric   // Iterate as long as defined lanes/used lanes keep changing.
4660b57cec5SDimitry Andric   while (!Worklist.empty()) {
4670b57cec5SDimitry Andric     unsigned RegIdx = Worklist.front();
4680b57cec5SDimitry Andric     Worklist.pop_front();
4690b57cec5SDimitry Andric     WorklistMembers.reset(RegIdx);
4700b57cec5SDimitry Andric     VRegInfo &Info = VRegInfos[RegIdx];
471bdd1243dSDimitry Andric     Register Reg = Register::index2VirtReg(RegIdx);
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric     // Transfer UsedLanes to operands of DefMI (backwards dataflow).
4740b57cec5SDimitry Andric     MachineOperand &Def = *MRI->def_begin(Reg);
4750b57cec5SDimitry Andric     const MachineInstr &MI = *Def.getParent();
4760b57cec5SDimitry Andric     transferUsedLanesStep(MI, Info.UsedLanes);
4770b57cec5SDimitry Andric     // Transfer DefinedLanes to users of Reg (forward dataflow).
4780b57cec5SDimitry Andric     for (const MachineOperand &MO : MRI->use_nodbg_operands(Reg))
4790b57cec5SDimitry Andric       transferDefinedLanesStep(MO, Info.DefinedLanes);
4800b57cec5SDimitry Andric   }
4810b57cec5SDimitry Andric 
482fe6060f1SDimitry Andric   LLVM_DEBUG({
483fe6060f1SDimitry Andric     dbgs() << "Defined/Used lanes:\n";
484fe6060f1SDimitry Andric     for (unsigned RegIdx = 0; RegIdx < NumVirtRegs; ++RegIdx) {
485bdd1243dSDimitry Andric       Register Reg = Register::index2VirtReg(RegIdx);
4860b57cec5SDimitry Andric       const VRegInfo &Info = VRegInfos[RegIdx];
4870b57cec5SDimitry Andric       dbgs() << printReg(Reg, nullptr)
4880b57cec5SDimitry Andric              << " Used: " << PrintLaneMask(Info.UsedLanes)
4890b57cec5SDimitry Andric              << " Def: " << PrintLaneMask(Info.DefinedLanes) << '\n';
490fe6060f1SDimitry Andric     }
491fe6060f1SDimitry Andric     dbgs() << "\n";
492fe6060f1SDimitry Andric   });
493*06c3fb27SDimitry Andric }
4940b57cec5SDimitry Andric 
495*06c3fb27SDimitry Andric std::pair<bool, bool>
modifySubRegisterOperandStatus(const DeadLaneDetector & DLD,MachineFunction & MF)496*06c3fb27SDimitry Andric DetectDeadLanes::modifySubRegisterOperandStatus(const DeadLaneDetector &DLD,
497*06c3fb27SDimitry Andric                                                 MachineFunction &MF) {
49881ad6265SDimitry Andric   bool Changed = false;
4990b57cec5SDimitry Andric   bool Again = false;
5000b57cec5SDimitry Andric   // Mark operands as dead/unused.
5010b57cec5SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
5020b57cec5SDimitry Andric     for (MachineInstr &MI : MBB) {
5030b57cec5SDimitry Andric       for (MachineOperand &MO : MI.operands()) {
5040b57cec5SDimitry Andric         if (!MO.isReg())
5050b57cec5SDimitry Andric           continue;
5068bcb0991SDimitry Andric         Register Reg = MO.getReg();
507bdd1243dSDimitry Andric         if (!Reg.isVirtual())
5080b57cec5SDimitry Andric           continue;
5098bcb0991SDimitry Andric         unsigned RegIdx = Register::virtReg2Index(Reg);
510*06c3fb27SDimitry Andric         const DeadLaneDetector::VRegInfo &RegInfo = DLD.getVRegInfo(RegIdx);
5110b57cec5SDimitry Andric         if (MO.isDef() && !MO.isDead() && RegInfo.UsedLanes.none()) {
5120b57cec5SDimitry Andric           LLVM_DEBUG(dbgs()
5130b57cec5SDimitry Andric                      << "Marking operand '" << MO << "' as dead in " << MI);
5140b57cec5SDimitry Andric           MO.setIsDead();
51581ad6265SDimitry Andric           Changed = true;
5160b57cec5SDimitry Andric         }
5170b57cec5SDimitry Andric         if (MO.readsReg()) {
5180b57cec5SDimitry Andric           bool CrossCopy = false;
5190b57cec5SDimitry Andric           if (isUndefRegAtInput(MO, RegInfo)) {
5200b57cec5SDimitry Andric             LLVM_DEBUG(dbgs()
5210b57cec5SDimitry Andric                        << "Marking operand '" << MO << "' as undef in " << MI);
5220b57cec5SDimitry Andric             MO.setIsUndef();
52381ad6265SDimitry Andric             Changed = true;
524*06c3fb27SDimitry Andric           } else if (isUndefInput(DLD, MO, &CrossCopy)) {
5250b57cec5SDimitry Andric             LLVM_DEBUG(dbgs()
5260b57cec5SDimitry Andric                        << "Marking operand '" << MO << "' as undef in " << MI);
5270b57cec5SDimitry Andric             MO.setIsUndef();
52881ad6265SDimitry Andric             Changed = true;
5290b57cec5SDimitry Andric             if (CrossCopy)
5300b57cec5SDimitry Andric               Again = true;
5310b57cec5SDimitry Andric           }
5320b57cec5SDimitry Andric         }
5330b57cec5SDimitry Andric       }
5340b57cec5SDimitry Andric     }
5350b57cec5SDimitry Andric   }
5360b57cec5SDimitry Andric 
53781ad6265SDimitry Andric   return std::make_pair(Changed, Again);
5380b57cec5SDimitry Andric }
5390b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)5400b57cec5SDimitry Andric bool DetectDeadLanes::runOnMachineFunction(MachineFunction &MF) {
5410b57cec5SDimitry Andric   // Don't bother if we won't track subregister liveness later.  This pass is
5420b57cec5SDimitry Andric   // required for correctness if subregister liveness is enabled because the
5430b57cec5SDimitry Andric   // register coalescer cannot deal with hidden dead defs. However without
5440b57cec5SDimitry Andric   // subregister liveness enabled, the expected benefits of this pass are small
5450b57cec5SDimitry Andric   // so we safe the compile time.
5460b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
5470b57cec5SDimitry Andric   if (!MRI->subRegLivenessEnabled()) {
5480b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Skipping Detect dead lanes pass\n");
5490b57cec5SDimitry Andric     return false;
5500b57cec5SDimitry Andric   }
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   TRI = MRI->getTargetRegisterInfo();
5530b57cec5SDimitry Andric 
554*06c3fb27SDimitry Andric   DeadLaneDetector DLD(MRI, TRI);
5550b57cec5SDimitry Andric 
55681ad6265SDimitry Andric   bool Changed = false;
5570b57cec5SDimitry Andric   bool Again;
5580b57cec5SDimitry Andric   do {
559*06c3fb27SDimitry Andric     DLD.computeSubRegisterLaneBitInfo();
56081ad6265SDimitry Andric     bool LocalChanged;
561*06c3fb27SDimitry Andric     std::tie(LocalChanged, Again) = modifySubRegisterOperandStatus(DLD, MF);
56281ad6265SDimitry Andric     Changed |= LocalChanged;
5630b57cec5SDimitry Andric   } while (Again);
5640b57cec5SDimitry Andric 
56581ad6265SDimitry Andric   return Changed;
5660b57cec5SDimitry Andric }
567