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 
280b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
320b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
330b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
340b57cec5SDimitry Andric #include "llvm/InitializePasses.h"
350b57cec5SDimitry Andric #include "llvm/Pass.h"
360b57cec5SDimitry Andric #include "llvm/PassRegistry.h"
370b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
380b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
39e8d8bef9SDimitry Andric #include <deque>
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric using namespace llvm;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric #define DEBUG_TYPE "detect-dead-lanes"
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric namespace {
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric /// Contains a bitmask of which lanes of a given virtual register are
480b57cec5SDimitry Andric /// defined and which ones are actually used.
490b57cec5SDimitry Andric struct VRegInfo {
500b57cec5SDimitry Andric   LaneBitmask UsedLanes;
510b57cec5SDimitry Andric   LaneBitmask DefinedLanes;
520b57cec5SDimitry Andric };
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric class DetectDeadLanes : public MachineFunctionPass {
550b57cec5SDimitry Andric public:
560b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   static char ID;
590b57cec5SDimitry Andric   DetectDeadLanes() : MachineFunctionPass(ID) {}
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   StringRef getPassName() const override { return "Detect Dead Lanes"; }
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
640b57cec5SDimitry Andric     AU.setPreservesCFG();
650b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
660b57cec5SDimitry Andric   }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric private:
690b57cec5SDimitry Andric   /// Add used lane bits on the register used by operand \p MO. This translates
700b57cec5SDimitry Andric   /// the bitmask based on the operands subregister, and puts the register into
710b57cec5SDimitry Andric   /// the worklist if any new bits were added.
720b57cec5SDimitry Andric   void addUsedLanesOnOperand(const MachineOperand &MO, LaneBitmask UsedLanes);
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   /// Given a bitmask \p UsedLanes for the used lanes on a def output of a
750b57cec5SDimitry Andric   /// COPY-like instruction determine the lanes used on the use operands
760b57cec5SDimitry Andric   /// and call addUsedLanesOnOperand() for them.
770b57cec5SDimitry Andric   void transferUsedLanesStep(const MachineInstr &MI, LaneBitmask UsedLanes);
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   /// Given a use regiser operand \p Use and a mask of defined lanes, check
800b57cec5SDimitry Andric   /// if the operand belongs to a lowersToCopies() instruction, transfer the
810b57cec5SDimitry Andric   /// mask to the def and put the instruction into the worklist.
820b57cec5SDimitry Andric   void transferDefinedLanesStep(const MachineOperand &Use,
830b57cec5SDimitry Andric                                 LaneBitmask DefinedLanes);
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   /// Given a mask \p DefinedLanes of lanes defined at operand \p OpNum
860b57cec5SDimitry Andric   /// of COPY-like instruction, determine which lanes are defined at the output
870b57cec5SDimitry Andric   /// operand \p Def.
880b57cec5SDimitry Andric   LaneBitmask transferDefinedLanes(const MachineOperand &Def, unsigned OpNum,
890b57cec5SDimitry Andric                                    LaneBitmask DefinedLanes) const;
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   /// Given a mask \p UsedLanes used from the output of instruction \p MI
920b57cec5SDimitry Andric   /// determine which lanes are used from operand \p MO of this instruction.
930b57cec5SDimitry Andric   LaneBitmask transferUsedLanes(const MachineInstr &MI, LaneBitmask UsedLanes,
940b57cec5SDimitry Andric                                 const MachineOperand &MO) const;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   bool runOnce(MachineFunction &MF);
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   LaneBitmask determineInitialDefinedLanes(unsigned Reg);
990b57cec5SDimitry Andric   LaneBitmask determineInitialUsedLanes(unsigned Reg);
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   bool isUndefRegAtInput(const MachineOperand &MO,
1020b57cec5SDimitry Andric                          const VRegInfo &RegInfo) const;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   bool isUndefInput(const MachineOperand &MO, bool *CrossCopy) const;
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   const MachineRegisterInfo *MRI;
1070b57cec5SDimitry Andric   const TargetRegisterInfo *TRI;
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   void PutInWorklist(unsigned RegIdx) {
1100b57cec5SDimitry Andric     if (WorklistMembers.test(RegIdx))
1110b57cec5SDimitry Andric       return;
1120b57cec5SDimitry Andric     WorklistMembers.set(RegIdx);
1130b57cec5SDimitry Andric     Worklist.push_back(RegIdx);
1140b57cec5SDimitry Andric   }
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   VRegInfo *VRegInfos;
1170b57cec5SDimitry Andric   /// Worklist containing virtreg indexes.
1180b57cec5SDimitry Andric   std::deque<unsigned> Worklist;
1190b57cec5SDimitry Andric   BitVector WorklistMembers;
1200b57cec5SDimitry Andric   /// This bitvector is set for each vreg index where the vreg is defined
1210b57cec5SDimitry Andric   /// by an instruction where lowersToCopies()==true.
1220b57cec5SDimitry Andric   BitVector DefinedByCopy;
1230b57cec5SDimitry Andric };
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric } // end anonymous namespace
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric char DetectDeadLanes::ID = 0;
1280b57cec5SDimitry Andric char &llvm::DetectDeadLanesID = DetectDeadLanes::ID;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric INITIALIZE_PASS(DetectDeadLanes, DEBUG_TYPE, "Detect Dead Lanes", false, false)
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric /// Returns true if \p MI will get lowered to a series of COPY instructions.
1330b57cec5SDimitry Andric /// We call this a COPY-like instruction.
1340b57cec5SDimitry Andric static bool lowersToCopies(const MachineInstr &MI) {
1350b57cec5SDimitry Andric   // Note: We could support instructions with MCInstrDesc::isRegSequenceLike(),
1360b57cec5SDimitry Andric   // isExtractSubRegLike(), isInsertSubregLike() in the future even though they
1370b57cec5SDimitry Andric   // are not lowered to a COPY.
1380b57cec5SDimitry Andric   switch (MI.getOpcode()) {
1390b57cec5SDimitry Andric   case TargetOpcode::COPY:
1400b57cec5SDimitry Andric   case TargetOpcode::PHI:
1410b57cec5SDimitry Andric   case TargetOpcode::INSERT_SUBREG:
1420b57cec5SDimitry Andric   case TargetOpcode::REG_SEQUENCE:
1430b57cec5SDimitry Andric   case TargetOpcode::EXTRACT_SUBREG:
1440b57cec5SDimitry Andric     return true;
1450b57cec5SDimitry Andric   }
1460b57cec5SDimitry Andric   return false;
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric static bool isCrossCopy(const MachineRegisterInfo &MRI,
1500b57cec5SDimitry Andric                         const MachineInstr &MI,
1510b57cec5SDimitry Andric                         const TargetRegisterClass *DstRC,
1520b57cec5SDimitry Andric                         const MachineOperand &MO) {
1530b57cec5SDimitry Andric   assert(lowersToCopies(MI));
1548bcb0991SDimitry Andric   Register SrcReg = MO.getReg();
1550b57cec5SDimitry Andric   const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
1560b57cec5SDimitry Andric   if (DstRC == SrcRC)
1570b57cec5SDimitry Andric     return false;
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   unsigned SrcSubIdx = MO.getSubReg();
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
1620b57cec5SDimitry Andric   unsigned DstSubIdx = 0;
1630b57cec5SDimitry Andric   switch (MI.getOpcode()) {
1640b57cec5SDimitry Andric   case TargetOpcode::INSERT_SUBREG:
1650b57cec5SDimitry Andric     if (MI.getOperandNo(&MO) == 2)
1660b57cec5SDimitry Andric       DstSubIdx = MI.getOperand(3).getImm();
1670b57cec5SDimitry Andric     break;
1680b57cec5SDimitry Andric   case TargetOpcode::REG_SEQUENCE: {
1690b57cec5SDimitry Andric     unsigned OpNum = MI.getOperandNo(&MO);
1700b57cec5SDimitry Andric     DstSubIdx = MI.getOperand(OpNum+1).getImm();
1710b57cec5SDimitry Andric     break;
1720b57cec5SDimitry Andric   }
1730b57cec5SDimitry Andric   case TargetOpcode::EXTRACT_SUBREG: {
1740b57cec5SDimitry Andric     unsigned SubReg = MI.getOperand(2).getImm();
1750b57cec5SDimitry Andric     SrcSubIdx = TRI.composeSubRegIndices(SubReg, SrcSubIdx);
1760b57cec5SDimitry Andric   }
1770b57cec5SDimitry Andric   }
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   unsigned PreA, PreB; // Unused.
1800b57cec5SDimitry Andric   if (SrcSubIdx && DstSubIdx)
1810b57cec5SDimitry Andric     return !TRI.getCommonSuperRegClass(SrcRC, SrcSubIdx, DstRC, DstSubIdx, PreA,
1820b57cec5SDimitry Andric                                        PreB);
1830b57cec5SDimitry Andric   if (SrcSubIdx)
1840b57cec5SDimitry Andric     return !TRI.getMatchingSuperRegClass(SrcRC, DstRC, SrcSubIdx);
1850b57cec5SDimitry Andric   if (DstSubIdx)
1860b57cec5SDimitry Andric     return !TRI.getMatchingSuperRegClass(DstRC, SrcRC, DstSubIdx);
1870b57cec5SDimitry Andric   return !TRI.getCommonSubClass(SrcRC, DstRC);
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric void DetectDeadLanes::addUsedLanesOnOperand(const MachineOperand &MO,
1910b57cec5SDimitry Andric                                             LaneBitmask UsedLanes) {
1920b57cec5SDimitry Andric   if (!MO.readsReg())
1930b57cec5SDimitry Andric     return;
1948bcb0991SDimitry Andric   Register MOReg = MO.getReg();
1958bcb0991SDimitry Andric   if (!Register::isVirtualRegister(MOReg))
1960b57cec5SDimitry Andric     return;
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   unsigned MOSubReg = MO.getSubReg();
1990b57cec5SDimitry Andric   if (MOSubReg != 0)
2000b57cec5SDimitry Andric     UsedLanes = TRI->composeSubRegIndexLaneMask(MOSubReg, UsedLanes);
2010b57cec5SDimitry Andric   UsedLanes &= MRI->getMaxLaneMaskForVReg(MOReg);
2020b57cec5SDimitry Andric 
2038bcb0991SDimitry Andric   unsigned MORegIdx = Register::virtReg2Index(MOReg);
2040b57cec5SDimitry Andric   VRegInfo &MORegInfo = VRegInfos[MORegIdx];
2050b57cec5SDimitry Andric   LaneBitmask PrevUsedLanes = MORegInfo.UsedLanes;
2060b57cec5SDimitry Andric   // Any change at all?
2070b57cec5SDimitry Andric   if ((UsedLanes & ~PrevUsedLanes).none())
2080b57cec5SDimitry Andric     return;
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   // Set UsedLanes and remember instruction for further propagation.
2110b57cec5SDimitry Andric   MORegInfo.UsedLanes = PrevUsedLanes | UsedLanes;
2120b57cec5SDimitry Andric   if (DefinedByCopy.test(MORegIdx))
2130b57cec5SDimitry Andric     PutInWorklist(MORegIdx);
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric void DetectDeadLanes::transferUsedLanesStep(const MachineInstr &MI,
2170b57cec5SDimitry Andric                                             LaneBitmask UsedLanes) {
2180b57cec5SDimitry Andric   for (const MachineOperand &MO : MI.uses()) {
2198bcb0991SDimitry Andric     if (!MO.isReg() || !Register::isVirtualRegister(MO.getReg()))
2200b57cec5SDimitry Andric       continue;
2210b57cec5SDimitry Andric     LaneBitmask UsedOnMO = transferUsedLanes(MI, UsedLanes, MO);
2220b57cec5SDimitry Andric     addUsedLanesOnOperand(MO, UsedOnMO);
2230b57cec5SDimitry Andric   }
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric LaneBitmask DetectDeadLanes::transferUsedLanes(const MachineInstr &MI,
2270b57cec5SDimitry Andric                                                LaneBitmask UsedLanes,
2280b57cec5SDimitry Andric                                                const MachineOperand &MO) const {
2290b57cec5SDimitry Andric   unsigned OpNum = MI.getOperandNo(&MO);
2308bcb0991SDimitry Andric   assert(lowersToCopies(MI) &&
2318bcb0991SDimitry Andric          DefinedByCopy[Register::virtReg2Index(MI.getOperand(0).getReg())]);
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric   switch (MI.getOpcode()) {
2340b57cec5SDimitry Andric   case TargetOpcode::COPY:
2350b57cec5SDimitry Andric   case TargetOpcode::PHI:
2360b57cec5SDimitry Andric     return UsedLanes;
2370b57cec5SDimitry Andric   case TargetOpcode::REG_SEQUENCE: {
2380b57cec5SDimitry Andric     assert(OpNum % 2 == 1);
2390b57cec5SDimitry Andric     unsigned SubIdx = MI.getOperand(OpNum + 1).getImm();
2400b57cec5SDimitry Andric     return TRI->reverseComposeSubRegIndexLaneMask(SubIdx, UsedLanes);
2410b57cec5SDimitry Andric   }
2420b57cec5SDimitry Andric   case TargetOpcode::INSERT_SUBREG: {
2430b57cec5SDimitry Andric     unsigned SubIdx = MI.getOperand(3).getImm();
2440b57cec5SDimitry Andric     LaneBitmask MO2UsedLanes =
2450b57cec5SDimitry Andric         TRI->reverseComposeSubRegIndexLaneMask(SubIdx, UsedLanes);
2460b57cec5SDimitry Andric     if (OpNum == 2)
2470b57cec5SDimitry Andric       return MO2UsedLanes;
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric     const MachineOperand &Def = MI.getOperand(0);
2508bcb0991SDimitry Andric     Register DefReg = Def.getReg();
2510b57cec5SDimitry Andric     const TargetRegisterClass *RC = MRI->getRegClass(DefReg);
2520b57cec5SDimitry Andric     LaneBitmask MO1UsedLanes;
2530b57cec5SDimitry Andric     if (RC->CoveredBySubRegs)
2540b57cec5SDimitry Andric       MO1UsedLanes = UsedLanes & ~TRI->getSubRegIndexLaneMask(SubIdx);
2550b57cec5SDimitry Andric     else
2560b57cec5SDimitry Andric       MO1UsedLanes = RC->LaneMask;
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric     assert(OpNum == 1);
2590b57cec5SDimitry Andric     return MO1UsedLanes;
2600b57cec5SDimitry Andric   }
2610b57cec5SDimitry Andric   case TargetOpcode::EXTRACT_SUBREG: {
2620b57cec5SDimitry Andric     assert(OpNum == 1);
2630b57cec5SDimitry Andric     unsigned SubIdx = MI.getOperand(2).getImm();
2640b57cec5SDimitry Andric     return TRI->composeSubRegIndexLaneMask(SubIdx, UsedLanes);
2650b57cec5SDimitry Andric   }
2660b57cec5SDimitry Andric   default:
2670b57cec5SDimitry Andric     llvm_unreachable("function must be called with COPY-like instruction");
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric void DetectDeadLanes::transferDefinedLanesStep(const MachineOperand &Use,
2720b57cec5SDimitry Andric                                                LaneBitmask DefinedLanes) {
2730b57cec5SDimitry Andric   if (!Use.readsReg())
2740b57cec5SDimitry Andric     return;
2750b57cec5SDimitry Andric   // Check whether the operand writes a vreg and is part of a COPY-like
2760b57cec5SDimitry Andric   // instruction.
2770b57cec5SDimitry Andric   const MachineInstr &MI = *Use.getParent();
2780b57cec5SDimitry Andric   if (MI.getDesc().getNumDefs() != 1)
2790b57cec5SDimitry Andric     return;
2800b57cec5SDimitry Andric   // FIXME: PATCHPOINT instructions announce a Def that does not always exist,
2810b57cec5SDimitry Andric   // they really need to be modeled differently!
2820b57cec5SDimitry Andric   if (MI.getOpcode() == TargetOpcode::PATCHPOINT)
2830b57cec5SDimitry Andric     return;
2840b57cec5SDimitry Andric   const MachineOperand &Def = *MI.defs().begin();
2858bcb0991SDimitry Andric   Register DefReg = Def.getReg();
2868bcb0991SDimitry Andric   if (!Register::isVirtualRegister(DefReg))
2870b57cec5SDimitry Andric     return;
2888bcb0991SDimitry Andric   unsigned DefRegIdx = Register::virtReg2Index(DefReg);
2890b57cec5SDimitry Andric   if (!DefinedByCopy.test(DefRegIdx))
2900b57cec5SDimitry Andric     return;
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   unsigned OpNum = MI.getOperandNo(&Use);
2930b57cec5SDimitry Andric   DefinedLanes =
2940b57cec5SDimitry Andric       TRI->reverseComposeSubRegIndexLaneMask(Use.getSubReg(), DefinedLanes);
2950b57cec5SDimitry Andric   DefinedLanes = transferDefinedLanes(Def, OpNum, DefinedLanes);
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric   VRegInfo &RegInfo = VRegInfos[DefRegIdx];
2980b57cec5SDimitry Andric   LaneBitmask PrevDefinedLanes = RegInfo.DefinedLanes;
2990b57cec5SDimitry Andric   // Any change at all?
3000b57cec5SDimitry Andric   if ((DefinedLanes & ~PrevDefinedLanes).none())
3010b57cec5SDimitry Andric     return;
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   RegInfo.DefinedLanes = PrevDefinedLanes | DefinedLanes;
3040b57cec5SDimitry Andric   PutInWorklist(DefRegIdx);
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric LaneBitmask DetectDeadLanes::transferDefinedLanes(const MachineOperand &Def,
3080b57cec5SDimitry Andric     unsigned OpNum, LaneBitmask DefinedLanes) const {
3090b57cec5SDimitry Andric   const MachineInstr &MI = *Def.getParent();
3100b57cec5SDimitry Andric   // Translate DefinedLanes if necessary.
3110b57cec5SDimitry Andric   switch (MI.getOpcode()) {
3120b57cec5SDimitry Andric   case TargetOpcode::REG_SEQUENCE: {
3130b57cec5SDimitry Andric     unsigned SubIdx = MI.getOperand(OpNum + 1).getImm();
3140b57cec5SDimitry Andric     DefinedLanes = TRI->composeSubRegIndexLaneMask(SubIdx, DefinedLanes);
3150b57cec5SDimitry Andric     DefinedLanes &= TRI->getSubRegIndexLaneMask(SubIdx);
3160b57cec5SDimitry Andric     break;
3170b57cec5SDimitry Andric   }
3180b57cec5SDimitry Andric   case TargetOpcode::INSERT_SUBREG: {
3190b57cec5SDimitry Andric     unsigned SubIdx = MI.getOperand(3).getImm();
3200b57cec5SDimitry Andric     if (OpNum == 2) {
3210b57cec5SDimitry Andric       DefinedLanes = TRI->composeSubRegIndexLaneMask(SubIdx, DefinedLanes);
3220b57cec5SDimitry Andric       DefinedLanes &= TRI->getSubRegIndexLaneMask(SubIdx);
3230b57cec5SDimitry Andric     } else {
3240b57cec5SDimitry Andric       assert(OpNum == 1 && "INSERT_SUBREG must have two operands");
3250b57cec5SDimitry Andric       // Ignore lanes defined by operand 2.
3260b57cec5SDimitry Andric       DefinedLanes &= ~TRI->getSubRegIndexLaneMask(SubIdx);
3270b57cec5SDimitry Andric     }
3280b57cec5SDimitry Andric     break;
3290b57cec5SDimitry Andric   }
3300b57cec5SDimitry Andric   case TargetOpcode::EXTRACT_SUBREG: {
3310b57cec5SDimitry Andric     unsigned SubIdx = MI.getOperand(2).getImm();
3320b57cec5SDimitry Andric     assert(OpNum == 1 && "EXTRACT_SUBREG must have one register operand only");
3330b57cec5SDimitry Andric     DefinedLanes = TRI->reverseComposeSubRegIndexLaneMask(SubIdx, DefinedLanes);
3340b57cec5SDimitry Andric     break;
3350b57cec5SDimitry Andric   }
3360b57cec5SDimitry Andric   case TargetOpcode::COPY:
3370b57cec5SDimitry Andric   case TargetOpcode::PHI:
3380b57cec5SDimitry Andric     break;
3390b57cec5SDimitry Andric   default:
3400b57cec5SDimitry Andric     llvm_unreachable("function must be called with COPY-like instruction");
3410b57cec5SDimitry Andric   }
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   assert(Def.getSubReg() == 0 &&
3440b57cec5SDimitry Andric          "Should not have subregister defs in machine SSA phase");
3450b57cec5SDimitry Andric   DefinedLanes &= MRI->getMaxLaneMaskForVReg(Def.getReg());
3460b57cec5SDimitry Andric   return DefinedLanes;
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric LaneBitmask DetectDeadLanes::determineInitialDefinedLanes(unsigned Reg) {
3500b57cec5SDimitry Andric   // Live-In or unused registers have no definition but are considered fully
3510b57cec5SDimitry Andric   // defined.
3520b57cec5SDimitry Andric   if (!MRI->hasOneDef(Reg))
3530b57cec5SDimitry Andric     return LaneBitmask::getAll();
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   const MachineOperand &Def = *MRI->def_begin(Reg);
3560b57cec5SDimitry Andric   const MachineInstr &DefMI = *Def.getParent();
3570b57cec5SDimitry Andric   if (lowersToCopies(DefMI)) {
3580b57cec5SDimitry Andric     // Start optimisatically with no used or defined lanes for copy
3590b57cec5SDimitry Andric     // instructions. The following dataflow analysis will add more bits.
3608bcb0991SDimitry Andric     unsigned RegIdx = Register::virtReg2Index(Reg);
3610b57cec5SDimitry Andric     DefinedByCopy.set(RegIdx);
3620b57cec5SDimitry Andric     PutInWorklist(RegIdx);
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric     if (Def.isDead())
3650b57cec5SDimitry Andric       return LaneBitmask::getNone();
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric     // COPY/PHI can copy across unrelated register classes (example: float/int)
3680b57cec5SDimitry Andric     // with incompatible subregister structure. Do not include these in the
3690b57cec5SDimitry Andric     // dataflow analysis since we cannot transfer lanemasks in a meaningful way.
3700b57cec5SDimitry Andric     const TargetRegisterClass *DefRC = MRI->getRegClass(Reg);
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric     // Determine initially DefinedLanes.
3730b57cec5SDimitry Andric     LaneBitmask DefinedLanes;
3740b57cec5SDimitry Andric     for (const MachineOperand &MO : DefMI.uses()) {
3750b57cec5SDimitry Andric       if (!MO.isReg() || !MO.readsReg())
3760b57cec5SDimitry Andric         continue;
3778bcb0991SDimitry Andric       Register MOReg = MO.getReg();
3780b57cec5SDimitry Andric       if (!MOReg)
3790b57cec5SDimitry Andric         continue;
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric       LaneBitmask MODefinedLanes;
3828bcb0991SDimitry Andric       if (Register::isPhysicalRegister(MOReg)) {
3830b57cec5SDimitry Andric         MODefinedLanes = LaneBitmask::getAll();
3840b57cec5SDimitry Andric       } else if (isCrossCopy(*MRI, DefMI, DefRC, MO)) {
3850b57cec5SDimitry Andric         MODefinedLanes = LaneBitmask::getAll();
3860b57cec5SDimitry Andric       } else {
3878bcb0991SDimitry Andric         assert(Register::isVirtualRegister(MOReg));
3880b57cec5SDimitry Andric         if (MRI->hasOneDef(MOReg)) {
3890b57cec5SDimitry Andric           const MachineOperand &MODef = *MRI->def_begin(MOReg);
3900b57cec5SDimitry Andric           const MachineInstr &MODefMI = *MODef.getParent();
3910b57cec5SDimitry Andric           // Bits from copy-like operations will be added later.
3920b57cec5SDimitry Andric           if (lowersToCopies(MODefMI) || MODefMI.isImplicitDef())
3930b57cec5SDimitry Andric             continue;
3940b57cec5SDimitry Andric         }
3950b57cec5SDimitry Andric         unsigned MOSubReg = MO.getSubReg();
3960b57cec5SDimitry Andric         MODefinedLanes = MRI->getMaxLaneMaskForVReg(MOReg);
3970b57cec5SDimitry Andric         MODefinedLanes = TRI->reverseComposeSubRegIndexLaneMask(
3980b57cec5SDimitry Andric             MOSubReg, MODefinedLanes);
3990b57cec5SDimitry Andric       }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric       unsigned OpNum = DefMI.getOperandNo(&MO);
4020b57cec5SDimitry Andric       DefinedLanes |= transferDefinedLanes(Def, OpNum, MODefinedLanes);
4030b57cec5SDimitry Andric     }
4040b57cec5SDimitry Andric     return DefinedLanes;
4050b57cec5SDimitry Andric   }
4060b57cec5SDimitry Andric   if (DefMI.isImplicitDef() || Def.isDead())
4070b57cec5SDimitry Andric     return LaneBitmask::getNone();
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   assert(Def.getSubReg() == 0 &&
4100b57cec5SDimitry Andric          "Should not have subregister defs in machine SSA phase");
4110b57cec5SDimitry Andric   return MRI->getMaxLaneMaskForVReg(Reg);
4120b57cec5SDimitry Andric }
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric LaneBitmask DetectDeadLanes::determineInitialUsedLanes(unsigned Reg) {
4150b57cec5SDimitry Andric   LaneBitmask UsedLanes = LaneBitmask::getNone();
4160b57cec5SDimitry Andric   for (const MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
4170b57cec5SDimitry Andric     if (!MO.readsReg())
4180b57cec5SDimitry Andric       continue;
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric     const MachineInstr &UseMI = *MO.getParent();
4210b57cec5SDimitry Andric     if (UseMI.isKill())
4220b57cec5SDimitry Andric       continue;
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric     unsigned SubReg = MO.getSubReg();
4250b57cec5SDimitry Andric     if (lowersToCopies(UseMI)) {
4260b57cec5SDimitry Andric       assert(UseMI.getDesc().getNumDefs() == 1);
4270b57cec5SDimitry Andric       const MachineOperand &Def = *UseMI.defs().begin();
4288bcb0991SDimitry Andric       Register DefReg = Def.getReg();
4290b57cec5SDimitry Andric       // The used lanes of COPY-like instruction operands are determined by the
4300b57cec5SDimitry Andric       // following dataflow analysis.
4318bcb0991SDimitry Andric       if (Register::isVirtualRegister(DefReg)) {
4320b57cec5SDimitry Andric         // But ignore copies across incompatible register classes.
4330b57cec5SDimitry Andric         bool CrossCopy = false;
4340b57cec5SDimitry Andric         if (lowersToCopies(UseMI)) {
4350b57cec5SDimitry Andric           const TargetRegisterClass *DstRC = MRI->getRegClass(DefReg);
4360b57cec5SDimitry Andric           CrossCopy = isCrossCopy(*MRI, UseMI, DstRC, MO);
4370b57cec5SDimitry Andric           if (CrossCopy)
4380b57cec5SDimitry Andric             LLVM_DEBUG(dbgs() << "Copy across incompatible classes: " << UseMI);
4390b57cec5SDimitry Andric         }
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric         if (!CrossCopy)
4420b57cec5SDimitry Andric           continue;
4430b57cec5SDimitry Andric       }
4440b57cec5SDimitry Andric     }
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric     // Shortcut: All lanes are used.
4470b57cec5SDimitry Andric     if (SubReg == 0)
4480b57cec5SDimitry Andric       return MRI->getMaxLaneMaskForVReg(Reg);
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric     UsedLanes |= TRI->getSubRegIndexLaneMask(SubReg);
4510b57cec5SDimitry Andric   }
4520b57cec5SDimitry Andric   return UsedLanes;
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric bool DetectDeadLanes::isUndefRegAtInput(const MachineOperand &MO,
4560b57cec5SDimitry Andric                                         const VRegInfo &RegInfo) const {
4570b57cec5SDimitry Andric   unsigned SubReg = MO.getSubReg();
4580b57cec5SDimitry Andric   LaneBitmask Mask = TRI->getSubRegIndexLaneMask(SubReg);
4590b57cec5SDimitry Andric   return (RegInfo.DefinedLanes & RegInfo.UsedLanes & Mask).none();
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric bool DetectDeadLanes::isUndefInput(const MachineOperand &MO,
4630b57cec5SDimitry Andric                                    bool *CrossCopy) const {
4640b57cec5SDimitry Andric   if (!MO.isUse())
4650b57cec5SDimitry Andric     return false;
4660b57cec5SDimitry Andric   const MachineInstr &MI = *MO.getParent();
4670b57cec5SDimitry Andric   if (!lowersToCopies(MI))
4680b57cec5SDimitry Andric     return false;
4690b57cec5SDimitry Andric   const MachineOperand &Def = MI.getOperand(0);
4708bcb0991SDimitry Andric   Register DefReg = Def.getReg();
4718bcb0991SDimitry Andric   if (!Register::isVirtualRegister(DefReg))
4720b57cec5SDimitry Andric     return false;
4738bcb0991SDimitry Andric   unsigned DefRegIdx = Register::virtReg2Index(DefReg);
4740b57cec5SDimitry Andric   if (!DefinedByCopy.test(DefRegIdx))
4750b57cec5SDimitry Andric     return false;
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   const VRegInfo &DefRegInfo = VRegInfos[DefRegIdx];
4780b57cec5SDimitry Andric   LaneBitmask UsedLanes = transferUsedLanes(MI, DefRegInfo.UsedLanes, MO);
4790b57cec5SDimitry Andric   if (UsedLanes.any())
4800b57cec5SDimitry Andric     return false;
4810b57cec5SDimitry Andric 
4828bcb0991SDimitry Andric   Register MOReg = MO.getReg();
4838bcb0991SDimitry Andric   if (Register::isVirtualRegister(MOReg)) {
4840b57cec5SDimitry Andric     const TargetRegisterClass *DstRC = MRI->getRegClass(DefReg);
4850b57cec5SDimitry Andric     *CrossCopy = isCrossCopy(*MRI, MI, DstRC, MO);
4860b57cec5SDimitry Andric   }
4870b57cec5SDimitry Andric   return true;
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric bool DetectDeadLanes::runOnce(MachineFunction &MF) {
4910b57cec5SDimitry Andric   // First pass: Populate defs/uses of vregs with initial values
4920b57cec5SDimitry Andric   unsigned NumVirtRegs = MRI->getNumVirtRegs();
4930b57cec5SDimitry Andric   for (unsigned RegIdx = 0; RegIdx < NumVirtRegs; ++RegIdx) {
4948bcb0991SDimitry Andric     unsigned Reg = Register::index2VirtReg(RegIdx);
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric     // Determine used/defined lanes and add copy instructions to worklist.
4970b57cec5SDimitry Andric     VRegInfo &Info = VRegInfos[RegIdx];
4980b57cec5SDimitry Andric     Info.DefinedLanes = determineInitialDefinedLanes(Reg);
4990b57cec5SDimitry Andric     Info.UsedLanes = determineInitialUsedLanes(Reg);
5000b57cec5SDimitry Andric   }
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   // Iterate as long as defined lanes/used lanes keep changing.
5030b57cec5SDimitry Andric   while (!Worklist.empty()) {
5040b57cec5SDimitry Andric     unsigned RegIdx = Worklist.front();
5050b57cec5SDimitry Andric     Worklist.pop_front();
5060b57cec5SDimitry Andric     WorklistMembers.reset(RegIdx);
5070b57cec5SDimitry Andric     VRegInfo &Info = VRegInfos[RegIdx];
5088bcb0991SDimitry Andric     unsigned Reg = Register::index2VirtReg(RegIdx);
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric     // Transfer UsedLanes to operands of DefMI (backwards dataflow).
5110b57cec5SDimitry Andric     MachineOperand &Def = *MRI->def_begin(Reg);
5120b57cec5SDimitry Andric     const MachineInstr &MI = *Def.getParent();
5130b57cec5SDimitry Andric     transferUsedLanesStep(MI, Info.UsedLanes);
5140b57cec5SDimitry Andric     // Transfer DefinedLanes to users of Reg (forward dataflow).
5150b57cec5SDimitry Andric     for (const MachineOperand &MO : MRI->use_nodbg_operands(Reg))
5160b57cec5SDimitry Andric       transferDefinedLanesStep(MO, Info.DefinedLanes);
5170b57cec5SDimitry Andric   }
5180b57cec5SDimitry Andric 
519fe6060f1SDimitry Andric   LLVM_DEBUG({
520fe6060f1SDimitry Andric     dbgs() << "Defined/Used lanes:\n";
521fe6060f1SDimitry Andric     for (unsigned RegIdx = 0; RegIdx < NumVirtRegs; ++RegIdx) {
5228bcb0991SDimitry Andric       unsigned Reg = Register::index2VirtReg(RegIdx);
5230b57cec5SDimitry Andric       const VRegInfo &Info = VRegInfos[RegIdx];
5240b57cec5SDimitry Andric       dbgs() << printReg(Reg, nullptr)
5250b57cec5SDimitry Andric              << " Used: " << PrintLaneMask(Info.UsedLanes)
5260b57cec5SDimitry Andric              << " Def: " << PrintLaneMask(Info.DefinedLanes) << '\n';
527fe6060f1SDimitry Andric     }
528fe6060f1SDimitry Andric     dbgs() << "\n";
529fe6060f1SDimitry Andric   });
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric   bool Again = false;
5320b57cec5SDimitry Andric   // Mark operands as dead/unused.
5330b57cec5SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
5340b57cec5SDimitry Andric     for (MachineInstr &MI : MBB) {
5350b57cec5SDimitry Andric       for (MachineOperand &MO : MI.operands()) {
5360b57cec5SDimitry Andric         if (!MO.isReg())
5370b57cec5SDimitry Andric           continue;
5388bcb0991SDimitry Andric         Register Reg = MO.getReg();
5398bcb0991SDimitry Andric         if (!Register::isVirtualRegister(Reg))
5400b57cec5SDimitry Andric           continue;
5418bcb0991SDimitry Andric         unsigned RegIdx = Register::virtReg2Index(Reg);
5420b57cec5SDimitry Andric         const VRegInfo &RegInfo = VRegInfos[RegIdx];
5430b57cec5SDimitry Andric         if (MO.isDef() && !MO.isDead() && RegInfo.UsedLanes.none()) {
5440b57cec5SDimitry Andric           LLVM_DEBUG(dbgs()
5450b57cec5SDimitry Andric                      << "Marking operand '" << MO << "' as dead in " << MI);
5460b57cec5SDimitry Andric           MO.setIsDead();
5470b57cec5SDimitry Andric         }
5480b57cec5SDimitry Andric         if (MO.readsReg()) {
5490b57cec5SDimitry Andric           bool CrossCopy = false;
5500b57cec5SDimitry Andric           if (isUndefRegAtInput(MO, RegInfo)) {
5510b57cec5SDimitry Andric             LLVM_DEBUG(dbgs()
5520b57cec5SDimitry Andric                        << "Marking operand '" << MO << "' as undef in " << MI);
5530b57cec5SDimitry Andric             MO.setIsUndef();
5540b57cec5SDimitry Andric           } else if (isUndefInput(MO, &CrossCopy)) {
5550b57cec5SDimitry Andric             LLVM_DEBUG(dbgs()
5560b57cec5SDimitry Andric                        << "Marking operand '" << MO << "' as undef in " << MI);
5570b57cec5SDimitry Andric             MO.setIsUndef();
5580b57cec5SDimitry Andric             if (CrossCopy)
5590b57cec5SDimitry Andric               Again = true;
5600b57cec5SDimitry Andric           }
5610b57cec5SDimitry Andric         }
5620b57cec5SDimitry Andric       }
5630b57cec5SDimitry Andric     }
5640b57cec5SDimitry Andric   }
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric   return Again;
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric bool DetectDeadLanes::runOnMachineFunction(MachineFunction &MF) {
5700b57cec5SDimitry Andric   // Don't bother if we won't track subregister liveness later.  This pass is
5710b57cec5SDimitry Andric   // required for correctness if subregister liveness is enabled because the
5720b57cec5SDimitry Andric   // register coalescer cannot deal with hidden dead defs. However without
5730b57cec5SDimitry Andric   // subregister liveness enabled, the expected benefits of this pass are small
5740b57cec5SDimitry Andric   // so we safe the compile time.
5750b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
5760b57cec5SDimitry Andric   if (!MRI->subRegLivenessEnabled()) {
5770b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Skipping Detect dead lanes pass\n");
5780b57cec5SDimitry Andric     return false;
5790b57cec5SDimitry Andric   }
5800b57cec5SDimitry Andric 
5810b57cec5SDimitry Andric   TRI = MRI->getTargetRegisterInfo();
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric   unsigned NumVirtRegs = MRI->getNumVirtRegs();
5840b57cec5SDimitry Andric   VRegInfos = new VRegInfo[NumVirtRegs];
5850b57cec5SDimitry Andric   WorklistMembers.resize(NumVirtRegs);
5860b57cec5SDimitry Andric   DefinedByCopy.resize(NumVirtRegs);
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric   bool Again;
5890b57cec5SDimitry Andric   do {
5900b57cec5SDimitry Andric     Again = runOnce(MF);
5910b57cec5SDimitry Andric   } while(Again);
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric   DefinedByCopy.clear();
5940b57cec5SDimitry Andric   WorklistMembers.clear();
5950b57cec5SDimitry Andric   delete[] VRegInfos;
5960b57cec5SDimitry Andric   return true;
5970b57cec5SDimitry Andric }
598