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