13ca95b02SDimitry Andric //===- DetectDeadLanes.cpp - SubRegister Lane Usage Analysis --*- C++ -*---===//
23ca95b02SDimitry Andric //
33ca95b02SDimitry Andric //                     The LLVM Compiler Infrastructure
43ca95b02SDimitry Andric //
53ca95b02SDimitry Andric // This file is distributed under the University of Illinois Open Source
63ca95b02SDimitry Andric // License. See LICENSE.TXT for details.
73ca95b02SDimitry Andric //
83ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
93ca95b02SDimitry Andric //
103ca95b02SDimitry Andric /// \file
113ca95b02SDimitry Andric /// Analysis that tracks defined/used subregister lanes across COPY instructions
123ca95b02SDimitry Andric /// and instructions that get lowered to a COPY (PHI, REG_SEQUENCE,
133ca95b02SDimitry Andric /// INSERT_SUBREG, EXTRACT_SUBREG).
143ca95b02SDimitry Andric /// The information is used to detect dead definitions and the usage of
153ca95b02SDimitry Andric /// (completely) undefined values and mark the operands as such.
163ca95b02SDimitry Andric /// This pass is necessary because the dead/undef status is not obvious anymore
173ca95b02SDimitry Andric /// when subregisters are involved.
183ca95b02SDimitry Andric ///
193ca95b02SDimitry Andric /// Example:
202cab237bSDimitry Andric ///    %0 = some definition
212cab237bSDimitry Andric ///    %1 = IMPLICIT_DEF
222cab237bSDimitry Andric ///    %2 = REG_SEQUENCE %0, sub0, %1, sub1
232cab237bSDimitry Andric ///    %3 = EXTRACT_SUBREG %2, sub1
242cab237bSDimitry Andric ///       = use %3
252cab237bSDimitry Andric /// The %0 definition is dead and %3 contains an undefined value.
263ca95b02SDimitry Andric //
273ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
283ca95b02SDimitry Andric 
293ca95b02SDimitry Andric #include <deque>
303ca95b02SDimitry Andric #include <vector>
313ca95b02SDimitry Andric 
323ca95b02SDimitry Andric #include "llvm/ADT/BitVector.h"
333ca95b02SDimitry Andric #include "llvm/ADT/SetVector.h"
343ca95b02SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
353ca95b02SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
363ca95b02SDimitry Andric #include "llvm/CodeGen/Passes.h"
372cab237bSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
382cab237bSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
393ca95b02SDimitry Andric #include "llvm/InitializePasses.h"
403ca95b02SDimitry Andric #include "llvm/Pass.h"
413ca95b02SDimitry Andric #include "llvm/PassRegistry.h"
423ca95b02SDimitry Andric #include "llvm/Support/Debug.h"
433ca95b02SDimitry Andric #include "llvm/Support/raw_ostream.h"
443ca95b02SDimitry Andric 
453ca95b02SDimitry Andric using namespace llvm;
463ca95b02SDimitry Andric 
473ca95b02SDimitry Andric #define DEBUG_TYPE "detect-dead-lanes"
483ca95b02SDimitry Andric 
493ca95b02SDimitry Andric namespace {
503ca95b02SDimitry Andric 
513ca95b02SDimitry Andric /// Contains a bitmask of which lanes of a given virtual register are
523ca95b02SDimitry Andric /// defined and which ones are actually used.
533ca95b02SDimitry Andric struct VRegInfo {
543ca95b02SDimitry Andric   LaneBitmask UsedLanes;
553ca95b02SDimitry Andric   LaneBitmask DefinedLanes;
563ca95b02SDimitry Andric };
573ca95b02SDimitry Andric 
583ca95b02SDimitry Andric class DetectDeadLanes : public MachineFunctionPass {
593ca95b02SDimitry Andric public:
603ca95b02SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
613ca95b02SDimitry Andric 
623ca95b02SDimitry Andric   static char ID;
DetectDeadLanes()633ca95b02SDimitry Andric   DetectDeadLanes() : MachineFunctionPass(ID) {}
643ca95b02SDimitry Andric 
getPassName() const65d88c1a5aSDimitry Andric   StringRef getPassName() const override { return "Detect Dead Lanes"; }
663ca95b02SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const673ca95b02SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
683ca95b02SDimitry Andric     AU.setPreservesCFG();
693ca95b02SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
703ca95b02SDimitry Andric   }
713ca95b02SDimitry Andric 
723ca95b02SDimitry Andric private:
733ca95b02SDimitry Andric   /// Add used lane bits on the register used by operand \p MO. This translates
743ca95b02SDimitry Andric   /// the bitmask based on the operands subregister, and puts the register into
753ca95b02SDimitry Andric   /// the worklist if any new bits were added.
763ca95b02SDimitry Andric   void addUsedLanesOnOperand(const MachineOperand &MO, LaneBitmask UsedLanes);
773ca95b02SDimitry Andric 
783ca95b02SDimitry Andric   /// Given a bitmask \p UsedLanes for the used lanes on a def output of a
793ca95b02SDimitry Andric   /// COPY-like instruction determine the lanes used on the use operands
803ca95b02SDimitry Andric   /// and call addUsedLanesOnOperand() for them.
813ca95b02SDimitry Andric   void transferUsedLanesStep(const MachineInstr &MI, LaneBitmask UsedLanes);
823ca95b02SDimitry Andric 
833ca95b02SDimitry Andric   /// Given a use regiser operand \p Use and a mask of defined lanes, check
843ca95b02SDimitry Andric   /// if the operand belongs to a lowersToCopies() instruction, transfer the
853ca95b02SDimitry Andric   /// mask to the def and put the instruction into the worklist.
863ca95b02SDimitry Andric   void transferDefinedLanesStep(const MachineOperand &Use,
873ca95b02SDimitry Andric                                 LaneBitmask DefinedLanes);
883ca95b02SDimitry Andric 
893ca95b02SDimitry Andric   /// Given a mask \p DefinedLanes of lanes defined at operand \p OpNum
903ca95b02SDimitry Andric   /// of COPY-like instruction, determine which lanes are defined at the output
913ca95b02SDimitry Andric   /// operand \p Def.
923ca95b02SDimitry Andric   LaneBitmask transferDefinedLanes(const MachineOperand &Def, unsigned OpNum,
933ca95b02SDimitry Andric                                    LaneBitmask DefinedLanes) const;
943ca95b02SDimitry Andric 
953ca95b02SDimitry Andric   /// Given a mask \p UsedLanes used from the output of instruction \p MI
963ca95b02SDimitry Andric   /// determine which lanes are used from operand \p MO of this instruction.
973ca95b02SDimitry Andric   LaneBitmask transferUsedLanes(const MachineInstr &MI, LaneBitmask UsedLanes,
983ca95b02SDimitry Andric                                 const MachineOperand &MO) const;
993ca95b02SDimitry Andric 
1003ca95b02SDimitry Andric   bool runOnce(MachineFunction &MF);
1013ca95b02SDimitry Andric 
1023ca95b02SDimitry Andric   LaneBitmask determineInitialDefinedLanes(unsigned Reg);
1033ca95b02SDimitry Andric   LaneBitmask determineInitialUsedLanes(unsigned Reg);
1043ca95b02SDimitry Andric 
1053ca95b02SDimitry Andric   bool isUndefRegAtInput(const MachineOperand &MO,
1063ca95b02SDimitry Andric                          const VRegInfo &RegInfo) const;
1073ca95b02SDimitry Andric 
1083ca95b02SDimitry Andric   bool isUndefInput(const MachineOperand &MO, bool *CrossCopy) const;
1093ca95b02SDimitry Andric 
1103ca95b02SDimitry Andric   const MachineRegisterInfo *MRI;
1113ca95b02SDimitry Andric   const TargetRegisterInfo *TRI;
1123ca95b02SDimitry Andric 
PutInWorklist(unsigned RegIdx)1133ca95b02SDimitry Andric   void PutInWorklist(unsigned RegIdx) {
1143ca95b02SDimitry Andric     if (WorklistMembers.test(RegIdx))
1153ca95b02SDimitry Andric       return;
1163ca95b02SDimitry Andric     WorklistMembers.set(RegIdx);
1173ca95b02SDimitry Andric     Worklist.push_back(RegIdx);
1183ca95b02SDimitry Andric   }
1193ca95b02SDimitry Andric 
1203ca95b02SDimitry Andric   VRegInfo *VRegInfos;
1213ca95b02SDimitry Andric   /// Worklist containing virtreg indexes.
1223ca95b02SDimitry Andric   std::deque<unsigned> Worklist;
1233ca95b02SDimitry Andric   BitVector WorklistMembers;
1243ca95b02SDimitry Andric   /// This bitvector is set for each vreg index where the vreg is defined
1253ca95b02SDimitry Andric   /// by an instruction where lowersToCopies()==true.
1263ca95b02SDimitry Andric   BitVector DefinedByCopy;
1273ca95b02SDimitry Andric };
1283ca95b02SDimitry Andric 
1293ca95b02SDimitry Andric } // end anonymous namespace
1303ca95b02SDimitry Andric 
1313ca95b02SDimitry Andric char DetectDeadLanes::ID = 0;
1323ca95b02SDimitry Andric char &llvm::DetectDeadLanesID = DetectDeadLanes::ID;
1333ca95b02SDimitry Andric 
134302affcbSDimitry Andric INITIALIZE_PASS(DetectDeadLanes, DEBUG_TYPE, "Detect Dead Lanes", false, false)
1353ca95b02SDimitry Andric 
1363ca95b02SDimitry Andric /// Returns true if \p MI will get lowered to a series of COPY instructions.
1373ca95b02SDimitry Andric /// We call this a COPY-like instruction.
lowersToCopies(const MachineInstr & MI)1383ca95b02SDimitry Andric static bool lowersToCopies(const MachineInstr &MI) {
1393ca95b02SDimitry Andric   // Note: We could support instructions with MCInstrDesc::isRegSequenceLike(),
1403ca95b02SDimitry Andric   // isExtractSubRegLike(), isInsertSubregLike() in the future even though they
1413ca95b02SDimitry Andric   // are not lowered to a COPY.
1423ca95b02SDimitry Andric   switch (MI.getOpcode()) {
1433ca95b02SDimitry Andric   case TargetOpcode::COPY:
1443ca95b02SDimitry Andric   case TargetOpcode::PHI:
1453ca95b02SDimitry Andric   case TargetOpcode::INSERT_SUBREG:
1463ca95b02SDimitry Andric   case TargetOpcode::REG_SEQUENCE:
1473ca95b02SDimitry Andric   case TargetOpcode::EXTRACT_SUBREG:
1483ca95b02SDimitry Andric     return true;
1493ca95b02SDimitry Andric   }
1503ca95b02SDimitry Andric   return false;
1513ca95b02SDimitry Andric }
1523ca95b02SDimitry Andric 
isCrossCopy(const MachineRegisterInfo & MRI,const MachineInstr & MI,const TargetRegisterClass * DstRC,const MachineOperand & MO)1533ca95b02SDimitry Andric static bool isCrossCopy(const MachineRegisterInfo &MRI,
1543ca95b02SDimitry Andric                         const MachineInstr &MI,
1553ca95b02SDimitry Andric                         const TargetRegisterClass *DstRC,
1563ca95b02SDimitry Andric                         const MachineOperand &MO) {
1573ca95b02SDimitry Andric   assert(lowersToCopies(MI));
1583ca95b02SDimitry Andric   unsigned SrcReg = MO.getReg();
1593ca95b02SDimitry Andric   const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
1603ca95b02SDimitry Andric   if (DstRC == SrcRC)
1613ca95b02SDimitry Andric     return false;
1623ca95b02SDimitry Andric 
1633ca95b02SDimitry Andric   unsigned SrcSubIdx = MO.getSubReg();
1643ca95b02SDimitry Andric 
1653ca95b02SDimitry Andric   const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
1663ca95b02SDimitry Andric   unsigned DstSubIdx = 0;
1673ca95b02SDimitry Andric   switch (MI.getOpcode()) {
1683ca95b02SDimitry Andric   case TargetOpcode::INSERT_SUBREG:
1693ca95b02SDimitry Andric     if (MI.getOperandNo(&MO) == 2)
1703ca95b02SDimitry Andric       DstSubIdx = MI.getOperand(3).getImm();
1713ca95b02SDimitry Andric     break;
1723ca95b02SDimitry Andric   case TargetOpcode::REG_SEQUENCE: {
1733ca95b02SDimitry Andric     unsigned OpNum = MI.getOperandNo(&MO);
1743ca95b02SDimitry Andric     DstSubIdx = MI.getOperand(OpNum+1).getImm();
1753ca95b02SDimitry Andric     break;
1763ca95b02SDimitry Andric   }
1773ca95b02SDimitry Andric   case TargetOpcode::EXTRACT_SUBREG: {
1783ca95b02SDimitry Andric     unsigned SubReg = MI.getOperand(2).getImm();
1793ca95b02SDimitry Andric     SrcSubIdx = TRI.composeSubRegIndices(SubReg, SrcSubIdx);
1803ca95b02SDimitry Andric   }
1813ca95b02SDimitry Andric   }
1823ca95b02SDimitry Andric 
1833ca95b02SDimitry Andric   unsigned PreA, PreB; // Unused.
1843ca95b02SDimitry Andric   if (SrcSubIdx && DstSubIdx)
1853ca95b02SDimitry Andric     return !TRI.getCommonSuperRegClass(SrcRC, SrcSubIdx, DstRC, DstSubIdx, PreA,
1863ca95b02SDimitry Andric                                        PreB);
1873ca95b02SDimitry Andric   if (SrcSubIdx)
1883ca95b02SDimitry Andric     return !TRI.getMatchingSuperRegClass(SrcRC, DstRC, SrcSubIdx);
1893ca95b02SDimitry Andric   if (DstSubIdx)
1903ca95b02SDimitry Andric     return !TRI.getMatchingSuperRegClass(DstRC, SrcRC, DstSubIdx);
1913ca95b02SDimitry Andric   return !TRI.getCommonSubClass(SrcRC, DstRC);
1923ca95b02SDimitry Andric }
1933ca95b02SDimitry Andric 
addUsedLanesOnOperand(const MachineOperand & MO,LaneBitmask UsedLanes)1943ca95b02SDimitry Andric void DetectDeadLanes::addUsedLanesOnOperand(const MachineOperand &MO,
1953ca95b02SDimitry Andric                                             LaneBitmask UsedLanes) {
1963ca95b02SDimitry Andric   if (!MO.readsReg())
1973ca95b02SDimitry Andric     return;
1983ca95b02SDimitry Andric   unsigned MOReg = MO.getReg();
1993ca95b02SDimitry Andric   if (!TargetRegisterInfo::isVirtualRegister(MOReg))
2003ca95b02SDimitry Andric     return;
2013ca95b02SDimitry Andric 
2023ca95b02SDimitry Andric   unsigned MOSubReg = MO.getSubReg();
2033ca95b02SDimitry Andric   if (MOSubReg != 0)
2043ca95b02SDimitry Andric     UsedLanes = TRI->composeSubRegIndexLaneMask(MOSubReg, UsedLanes);
2053ca95b02SDimitry Andric   UsedLanes &= MRI->getMaxLaneMaskForVReg(MOReg);
2063ca95b02SDimitry Andric 
2073ca95b02SDimitry Andric   unsigned MORegIdx = TargetRegisterInfo::virtReg2Index(MOReg);
2083ca95b02SDimitry Andric   VRegInfo &MORegInfo = VRegInfos[MORegIdx];
2093ca95b02SDimitry Andric   LaneBitmask PrevUsedLanes = MORegInfo.UsedLanes;
2103ca95b02SDimitry Andric   // Any change at all?
211d88c1a5aSDimitry Andric   if ((UsedLanes & ~PrevUsedLanes).none())
2123ca95b02SDimitry Andric     return;
2133ca95b02SDimitry Andric 
2143ca95b02SDimitry Andric   // Set UsedLanes and remember instruction for further propagation.
2153ca95b02SDimitry Andric   MORegInfo.UsedLanes = PrevUsedLanes | UsedLanes;
2163ca95b02SDimitry Andric   if (DefinedByCopy.test(MORegIdx))
2173ca95b02SDimitry Andric     PutInWorklist(MORegIdx);
2183ca95b02SDimitry Andric }
2193ca95b02SDimitry Andric 
transferUsedLanesStep(const MachineInstr & MI,LaneBitmask UsedLanes)2203ca95b02SDimitry Andric void DetectDeadLanes::transferUsedLanesStep(const MachineInstr &MI,
2213ca95b02SDimitry Andric                                             LaneBitmask UsedLanes) {
2223ca95b02SDimitry Andric   for (const MachineOperand &MO : MI.uses()) {
2233ca95b02SDimitry Andric     if (!MO.isReg() || !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
2243ca95b02SDimitry Andric       continue;
2253ca95b02SDimitry Andric     LaneBitmask UsedOnMO = transferUsedLanes(MI, UsedLanes, MO);
2263ca95b02SDimitry Andric     addUsedLanesOnOperand(MO, UsedOnMO);
2273ca95b02SDimitry Andric   }
2283ca95b02SDimitry Andric }
2293ca95b02SDimitry Andric 
transferUsedLanes(const MachineInstr & MI,LaneBitmask UsedLanes,const MachineOperand & MO) const2303ca95b02SDimitry Andric LaneBitmask DetectDeadLanes::transferUsedLanes(const MachineInstr &MI,
2313ca95b02SDimitry Andric                                                LaneBitmask UsedLanes,
2323ca95b02SDimitry Andric                                                const MachineOperand &MO) const {
2333ca95b02SDimitry Andric   unsigned OpNum = MI.getOperandNo(&MO);
2343ca95b02SDimitry Andric   assert(lowersToCopies(MI) && DefinedByCopy[
2353ca95b02SDimitry Andric            TargetRegisterInfo::virtReg2Index(MI.getOperand(0).getReg())]);
2363ca95b02SDimitry Andric 
2373ca95b02SDimitry Andric   switch (MI.getOpcode()) {
2383ca95b02SDimitry Andric   case TargetOpcode::COPY:
2393ca95b02SDimitry Andric   case TargetOpcode::PHI:
2403ca95b02SDimitry Andric     return UsedLanes;
2413ca95b02SDimitry Andric   case TargetOpcode::REG_SEQUENCE: {
2423ca95b02SDimitry Andric     assert(OpNum % 2 == 1);
2433ca95b02SDimitry Andric     unsigned SubIdx = MI.getOperand(OpNum + 1).getImm();
2443ca95b02SDimitry Andric     return TRI->reverseComposeSubRegIndexLaneMask(SubIdx, UsedLanes);
2453ca95b02SDimitry Andric   }
2463ca95b02SDimitry Andric   case TargetOpcode::INSERT_SUBREG: {
2473ca95b02SDimitry Andric     unsigned SubIdx = MI.getOperand(3).getImm();
2483ca95b02SDimitry Andric     LaneBitmask MO2UsedLanes =
2493ca95b02SDimitry Andric         TRI->reverseComposeSubRegIndexLaneMask(SubIdx, UsedLanes);
2503ca95b02SDimitry Andric     if (OpNum == 2)
2513ca95b02SDimitry Andric       return MO2UsedLanes;
2523ca95b02SDimitry Andric 
2533ca95b02SDimitry Andric     const MachineOperand &Def = MI.getOperand(0);
2543ca95b02SDimitry Andric     unsigned DefReg = Def.getReg();
2553ca95b02SDimitry Andric     const TargetRegisterClass *RC = MRI->getRegClass(DefReg);
2563ca95b02SDimitry Andric     LaneBitmask MO1UsedLanes;
2573ca95b02SDimitry Andric     if (RC->CoveredBySubRegs)
2583ca95b02SDimitry Andric       MO1UsedLanes = UsedLanes & ~TRI->getSubRegIndexLaneMask(SubIdx);
2593ca95b02SDimitry Andric     else
2603ca95b02SDimitry Andric       MO1UsedLanes = RC->LaneMask;
2613ca95b02SDimitry Andric 
2623ca95b02SDimitry Andric     assert(OpNum == 1);
2633ca95b02SDimitry Andric     return MO1UsedLanes;
2643ca95b02SDimitry Andric   }
2653ca95b02SDimitry Andric   case TargetOpcode::EXTRACT_SUBREG: {
2663ca95b02SDimitry Andric     assert(OpNum == 1);
2673ca95b02SDimitry Andric     unsigned SubIdx = MI.getOperand(2).getImm();
2683ca95b02SDimitry Andric     return TRI->composeSubRegIndexLaneMask(SubIdx, UsedLanes);
2693ca95b02SDimitry Andric   }
2703ca95b02SDimitry Andric   default:
2713ca95b02SDimitry Andric     llvm_unreachable("function must be called with COPY-like instruction");
2723ca95b02SDimitry Andric   }
2733ca95b02SDimitry Andric }
2743ca95b02SDimitry Andric 
transferDefinedLanesStep(const MachineOperand & Use,LaneBitmask DefinedLanes)2753ca95b02SDimitry Andric void DetectDeadLanes::transferDefinedLanesStep(const MachineOperand &Use,
2763ca95b02SDimitry Andric                                                LaneBitmask DefinedLanes) {
2773ca95b02SDimitry Andric   if (!Use.readsReg())
2783ca95b02SDimitry Andric     return;
2793ca95b02SDimitry Andric   // Check whether the operand writes a vreg and is part of a COPY-like
2803ca95b02SDimitry Andric   // instruction.
2813ca95b02SDimitry Andric   const MachineInstr &MI = *Use.getParent();
2823ca95b02SDimitry Andric   if (MI.getDesc().getNumDefs() != 1)
2833ca95b02SDimitry Andric     return;
2843ca95b02SDimitry Andric   // FIXME: PATCHPOINT instructions announce a Def that does not always exist,
2853ca95b02SDimitry Andric   // they really need to be modeled differently!
2863ca95b02SDimitry Andric   if (MI.getOpcode() == TargetOpcode::PATCHPOINT)
2873ca95b02SDimitry Andric     return;
2883ca95b02SDimitry Andric   const MachineOperand &Def = *MI.defs().begin();
2893ca95b02SDimitry Andric   unsigned DefReg = Def.getReg();
2903ca95b02SDimitry Andric   if (!TargetRegisterInfo::isVirtualRegister(DefReg))
2913ca95b02SDimitry Andric     return;
2923ca95b02SDimitry Andric   unsigned DefRegIdx = TargetRegisterInfo::virtReg2Index(DefReg);
2933ca95b02SDimitry Andric   if (!DefinedByCopy.test(DefRegIdx))
2943ca95b02SDimitry Andric     return;
2953ca95b02SDimitry Andric 
2963ca95b02SDimitry Andric   unsigned OpNum = MI.getOperandNo(&Use);
2973ca95b02SDimitry Andric   DefinedLanes =
2983ca95b02SDimitry Andric       TRI->reverseComposeSubRegIndexLaneMask(Use.getSubReg(), DefinedLanes);
2993ca95b02SDimitry Andric   DefinedLanes = transferDefinedLanes(Def, OpNum, DefinedLanes);
3003ca95b02SDimitry Andric 
3013ca95b02SDimitry Andric   VRegInfo &RegInfo = VRegInfos[DefRegIdx];
3023ca95b02SDimitry Andric   LaneBitmask PrevDefinedLanes = RegInfo.DefinedLanes;
3033ca95b02SDimitry Andric   // Any change at all?
304d88c1a5aSDimitry Andric   if ((DefinedLanes & ~PrevDefinedLanes).none())
3053ca95b02SDimitry Andric     return;
3063ca95b02SDimitry Andric 
3073ca95b02SDimitry Andric   RegInfo.DefinedLanes = PrevDefinedLanes | DefinedLanes;
3083ca95b02SDimitry Andric   PutInWorklist(DefRegIdx);
3093ca95b02SDimitry Andric }
3103ca95b02SDimitry Andric 
transferDefinedLanes(const MachineOperand & Def,unsigned OpNum,LaneBitmask DefinedLanes) const3113ca95b02SDimitry Andric LaneBitmask DetectDeadLanes::transferDefinedLanes(const MachineOperand &Def,
3123ca95b02SDimitry Andric     unsigned OpNum, LaneBitmask DefinedLanes) const {
3133ca95b02SDimitry Andric   const MachineInstr &MI = *Def.getParent();
3143ca95b02SDimitry Andric   // Translate DefinedLanes if necessary.
3153ca95b02SDimitry Andric   switch (MI.getOpcode()) {
3163ca95b02SDimitry Andric   case TargetOpcode::REG_SEQUENCE: {
3173ca95b02SDimitry Andric     unsigned SubIdx = MI.getOperand(OpNum + 1).getImm();
3183ca95b02SDimitry Andric     DefinedLanes = TRI->composeSubRegIndexLaneMask(SubIdx, DefinedLanes);
3193ca95b02SDimitry Andric     DefinedLanes &= TRI->getSubRegIndexLaneMask(SubIdx);
3203ca95b02SDimitry Andric     break;
3213ca95b02SDimitry Andric   }
3223ca95b02SDimitry Andric   case TargetOpcode::INSERT_SUBREG: {
3233ca95b02SDimitry Andric     unsigned SubIdx = MI.getOperand(3).getImm();
3243ca95b02SDimitry Andric     if (OpNum == 2) {
3253ca95b02SDimitry Andric       DefinedLanes = TRI->composeSubRegIndexLaneMask(SubIdx, DefinedLanes);
3263ca95b02SDimitry Andric       DefinedLanes &= TRI->getSubRegIndexLaneMask(SubIdx);
3273ca95b02SDimitry Andric     } else {
3283ca95b02SDimitry Andric       assert(OpNum == 1 && "INSERT_SUBREG must have two operands");
3293ca95b02SDimitry Andric       // Ignore lanes defined by operand 2.
3303ca95b02SDimitry Andric       DefinedLanes &= ~TRI->getSubRegIndexLaneMask(SubIdx);
3313ca95b02SDimitry Andric     }
3323ca95b02SDimitry Andric     break;
3333ca95b02SDimitry Andric   }
3343ca95b02SDimitry Andric   case TargetOpcode::EXTRACT_SUBREG: {
3353ca95b02SDimitry Andric     unsigned SubIdx = MI.getOperand(2).getImm();
3363ca95b02SDimitry Andric     assert(OpNum == 1 && "EXTRACT_SUBREG must have one register operand only");
3373ca95b02SDimitry Andric     DefinedLanes = TRI->reverseComposeSubRegIndexLaneMask(SubIdx, DefinedLanes);
3383ca95b02SDimitry Andric     break;
3393ca95b02SDimitry Andric   }
3403ca95b02SDimitry Andric   case TargetOpcode::COPY:
3413ca95b02SDimitry Andric   case TargetOpcode::PHI:
3423ca95b02SDimitry Andric     break;
3433ca95b02SDimitry Andric   default:
3443ca95b02SDimitry Andric     llvm_unreachable("function must be called with COPY-like instruction");
3453ca95b02SDimitry Andric   }
3463ca95b02SDimitry Andric 
3473ca95b02SDimitry Andric   assert(Def.getSubReg() == 0 &&
3483ca95b02SDimitry Andric          "Should not have subregister defs in machine SSA phase");
3493ca95b02SDimitry Andric   DefinedLanes &= MRI->getMaxLaneMaskForVReg(Def.getReg());
3503ca95b02SDimitry Andric   return DefinedLanes;
3513ca95b02SDimitry Andric }
3523ca95b02SDimitry Andric 
determineInitialDefinedLanes(unsigned Reg)3533ca95b02SDimitry Andric LaneBitmask DetectDeadLanes::determineInitialDefinedLanes(unsigned Reg) {
3543ca95b02SDimitry Andric   // Live-In or unused registers have no definition but are considered fully
3553ca95b02SDimitry Andric   // defined.
3563ca95b02SDimitry Andric   if (!MRI->hasOneDef(Reg))
357d88c1a5aSDimitry Andric     return LaneBitmask::getAll();
3583ca95b02SDimitry Andric 
3593ca95b02SDimitry Andric   const MachineOperand &Def = *MRI->def_begin(Reg);
3603ca95b02SDimitry Andric   const MachineInstr &DefMI = *Def.getParent();
3613ca95b02SDimitry Andric   if (lowersToCopies(DefMI)) {
3623ca95b02SDimitry Andric     // Start optimisatically with no used or defined lanes for copy
3633ca95b02SDimitry Andric     // instructions. The following dataflow analysis will add more bits.
3643ca95b02SDimitry Andric     unsigned RegIdx = TargetRegisterInfo::virtReg2Index(Reg);
3653ca95b02SDimitry Andric     DefinedByCopy.set(RegIdx);
3663ca95b02SDimitry Andric     PutInWorklist(RegIdx);
3673ca95b02SDimitry Andric 
3683ca95b02SDimitry Andric     if (Def.isDead())
369d88c1a5aSDimitry Andric       return LaneBitmask::getNone();
3703ca95b02SDimitry Andric 
3713ca95b02SDimitry Andric     // COPY/PHI can copy across unrelated register classes (example: float/int)
3723ca95b02SDimitry Andric     // with incompatible subregister structure. Do not include these in the
3733ca95b02SDimitry Andric     // dataflow analysis since we cannot transfer lanemasks in a meaningful way.
3743ca95b02SDimitry Andric     const TargetRegisterClass *DefRC = MRI->getRegClass(Reg);
3753ca95b02SDimitry Andric 
3763ca95b02SDimitry Andric     // Determine initially DefinedLanes.
377d88c1a5aSDimitry Andric     LaneBitmask DefinedLanes;
3783ca95b02SDimitry Andric     for (const MachineOperand &MO : DefMI.uses()) {
3793ca95b02SDimitry Andric       if (!MO.isReg() || !MO.readsReg())
3803ca95b02SDimitry Andric         continue;
3813ca95b02SDimitry Andric       unsigned MOReg = MO.getReg();
3823ca95b02SDimitry Andric       if (!MOReg)
3833ca95b02SDimitry Andric         continue;
3843ca95b02SDimitry Andric 
3853ca95b02SDimitry Andric       LaneBitmask MODefinedLanes;
3863ca95b02SDimitry Andric       if (TargetRegisterInfo::isPhysicalRegister(MOReg)) {
387d88c1a5aSDimitry Andric         MODefinedLanes = LaneBitmask::getAll();
3883ca95b02SDimitry Andric       } else if (isCrossCopy(*MRI, DefMI, DefRC, MO)) {
389d88c1a5aSDimitry Andric         MODefinedLanes = LaneBitmask::getAll();
3903ca95b02SDimitry Andric       } else {
3913ca95b02SDimitry Andric         assert(TargetRegisterInfo::isVirtualRegister(MOReg));
3923ca95b02SDimitry Andric         if (MRI->hasOneDef(MOReg)) {
3933ca95b02SDimitry Andric           const MachineOperand &MODef = *MRI->def_begin(MOReg);
3943ca95b02SDimitry Andric           const MachineInstr &MODefMI = *MODef.getParent();
3953ca95b02SDimitry Andric           // Bits from copy-like operations will be added later.
3963ca95b02SDimitry Andric           if (lowersToCopies(MODefMI) || MODefMI.isImplicitDef())
3973ca95b02SDimitry Andric             continue;
3983ca95b02SDimitry Andric         }
3993ca95b02SDimitry Andric         unsigned MOSubReg = MO.getSubReg();
4003ca95b02SDimitry Andric         MODefinedLanes = MRI->getMaxLaneMaskForVReg(MOReg);
4013ca95b02SDimitry Andric         MODefinedLanes = TRI->reverseComposeSubRegIndexLaneMask(
4023ca95b02SDimitry Andric             MOSubReg, MODefinedLanes);
4033ca95b02SDimitry Andric       }
4043ca95b02SDimitry Andric 
4053ca95b02SDimitry Andric       unsigned OpNum = DefMI.getOperandNo(&MO);
4063ca95b02SDimitry Andric       DefinedLanes |= transferDefinedLanes(Def, OpNum, MODefinedLanes);
4073ca95b02SDimitry Andric     }
4083ca95b02SDimitry Andric     return DefinedLanes;
4093ca95b02SDimitry Andric   }
4103ca95b02SDimitry Andric   if (DefMI.isImplicitDef() || Def.isDead())
411d88c1a5aSDimitry Andric     return LaneBitmask::getNone();
4123ca95b02SDimitry Andric 
4133ca95b02SDimitry Andric   assert(Def.getSubReg() == 0 &&
4143ca95b02SDimitry Andric          "Should not have subregister defs in machine SSA phase");
4153ca95b02SDimitry Andric   return MRI->getMaxLaneMaskForVReg(Reg);
4163ca95b02SDimitry Andric }
4173ca95b02SDimitry Andric 
determineInitialUsedLanes(unsigned Reg)4183ca95b02SDimitry Andric LaneBitmask DetectDeadLanes::determineInitialUsedLanes(unsigned Reg) {
419d88c1a5aSDimitry Andric   LaneBitmask UsedLanes = LaneBitmask::getNone();
4203ca95b02SDimitry Andric   for (const MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
4213ca95b02SDimitry Andric     if (!MO.readsReg())
4223ca95b02SDimitry Andric       continue;
4233ca95b02SDimitry Andric 
4243ca95b02SDimitry Andric     const MachineInstr &UseMI = *MO.getParent();
4253ca95b02SDimitry Andric     if (UseMI.isKill())
4263ca95b02SDimitry Andric       continue;
4273ca95b02SDimitry Andric 
4283ca95b02SDimitry Andric     unsigned SubReg = MO.getSubReg();
4293ca95b02SDimitry Andric     if (lowersToCopies(UseMI)) {
4303ca95b02SDimitry Andric       assert(UseMI.getDesc().getNumDefs() == 1);
4313ca95b02SDimitry Andric       const MachineOperand &Def = *UseMI.defs().begin();
4323ca95b02SDimitry Andric       unsigned DefReg = Def.getReg();
4333ca95b02SDimitry Andric       // The used lanes of COPY-like instruction operands are determined by the
4343ca95b02SDimitry Andric       // following dataflow analysis.
4353ca95b02SDimitry Andric       if (TargetRegisterInfo::isVirtualRegister(DefReg)) {
4363ca95b02SDimitry Andric         // But ignore copies across incompatible register classes.
4373ca95b02SDimitry Andric         bool CrossCopy = false;
4383ca95b02SDimitry Andric         if (lowersToCopies(UseMI)) {
4393ca95b02SDimitry Andric           const TargetRegisterClass *DstRC = MRI->getRegClass(DefReg);
4403ca95b02SDimitry Andric           CrossCopy = isCrossCopy(*MRI, UseMI, DstRC, MO);
4413ca95b02SDimitry Andric           if (CrossCopy)
442*4ba319b5SDimitry Andric             LLVM_DEBUG(dbgs() << "Copy across incompatible classes: " << UseMI);
4433ca95b02SDimitry Andric         }
4443ca95b02SDimitry Andric 
4453ca95b02SDimitry Andric         if (!CrossCopy)
4463ca95b02SDimitry Andric           continue;
4473ca95b02SDimitry Andric       }
4483ca95b02SDimitry Andric     }
4493ca95b02SDimitry Andric 
4503ca95b02SDimitry Andric     // Shortcut: All lanes are used.
4513ca95b02SDimitry Andric     if (SubReg == 0)
4523ca95b02SDimitry Andric       return MRI->getMaxLaneMaskForVReg(Reg);
4533ca95b02SDimitry Andric 
4543ca95b02SDimitry Andric     UsedLanes |= TRI->getSubRegIndexLaneMask(SubReg);
4553ca95b02SDimitry Andric   }
4563ca95b02SDimitry Andric   return UsedLanes;
4573ca95b02SDimitry Andric }
4583ca95b02SDimitry Andric 
isUndefRegAtInput(const MachineOperand & MO,const VRegInfo & RegInfo) const4593ca95b02SDimitry Andric bool DetectDeadLanes::isUndefRegAtInput(const MachineOperand &MO,
4603ca95b02SDimitry Andric                                         const VRegInfo &RegInfo) const {
4613ca95b02SDimitry Andric   unsigned SubReg = MO.getSubReg();
4623ca95b02SDimitry Andric   LaneBitmask Mask = TRI->getSubRegIndexLaneMask(SubReg);
463d88c1a5aSDimitry Andric   return (RegInfo.DefinedLanes & RegInfo.UsedLanes & Mask).none();
4643ca95b02SDimitry Andric }
4653ca95b02SDimitry Andric 
isUndefInput(const MachineOperand & MO,bool * CrossCopy) const4663ca95b02SDimitry Andric bool DetectDeadLanes::isUndefInput(const MachineOperand &MO,
4673ca95b02SDimitry Andric                                    bool *CrossCopy) const {
4683ca95b02SDimitry Andric   if (!MO.isUse())
4693ca95b02SDimitry Andric     return false;
4703ca95b02SDimitry Andric   const MachineInstr &MI = *MO.getParent();
4713ca95b02SDimitry Andric   if (!lowersToCopies(MI))
4723ca95b02SDimitry Andric     return false;
4733ca95b02SDimitry Andric   const MachineOperand &Def = MI.getOperand(0);
4743ca95b02SDimitry Andric   unsigned DefReg = Def.getReg();
4753ca95b02SDimitry Andric   if (!TargetRegisterInfo::isVirtualRegister(DefReg))
4763ca95b02SDimitry Andric     return false;
4773ca95b02SDimitry Andric   unsigned DefRegIdx = TargetRegisterInfo::virtReg2Index(DefReg);
4783ca95b02SDimitry Andric   if (!DefinedByCopy.test(DefRegIdx))
4793ca95b02SDimitry Andric     return false;
4803ca95b02SDimitry Andric 
4813ca95b02SDimitry Andric   const VRegInfo &DefRegInfo = VRegInfos[DefRegIdx];
4823ca95b02SDimitry Andric   LaneBitmask UsedLanes = transferUsedLanes(MI, DefRegInfo.UsedLanes, MO);
483d88c1a5aSDimitry Andric   if (UsedLanes.any())
4843ca95b02SDimitry Andric     return false;
4853ca95b02SDimitry Andric 
4863ca95b02SDimitry Andric   unsigned MOReg = MO.getReg();
4873ca95b02SDimitry Andric   if (TargetRegisterInfo::isVirtualRegister(MOReg)) {
4883ca95b02SDimitry Andric     const TargetRegisterClass *DstRC = MRI->getRegClass(DefReg);
4893ca95b02SDimitry Andric     *CrossCopy = isCrossCopy(*MRI, MI, DstRC, MO);
4903ca95b02SDimitry Andric   }
4913ca95b02SDimitry Andric   return true;
4923ca95b02SDimitry Andric }
4933ca95b02SDimitry Andric 
runOnce(MachineFunction & MF)4943ca95b02SDimitry Andric bool DetectDeadLanes::runOnce(MachineFunction &MF) {
4953ca95b02SDimitry Andric   // First pass: Populate defs/uses of vregs with initial values
4963ca95b02SDimitry Andric   unsigned NumVirtRegs = MRI->getNumVirtRegs();
4973ca95b02SDimitry Andric   for (unsigned RegIdx = 0; RegIdx < NumVirtRegs; ++RegIdx) {
4983ca95b02SDimitry Andric     unsigned Reg = TargetRegisterInfo::index2VirtReg(RegIdx);
4993ca95b02SDimitry Andric 
5003ca95b02SDimitry Andric     // Determine used/defined lanes and add copy instructions to worklist.
5013ca95b02SDimitry Andric     VRegInfo &Info = VRegInfos[RegIdx];
5023ca95b02SDimitry Andric     Info.DefinedLanes = determineInitialDefinedLanes(Reg);
5033ca95b02SDimitry Andric     Info.UsedLanes = determineInitialUsedLanes(Reg);
5043ca95b02SDimitry Andric   }
5053ca95b02SDimitry Andric 
5063ca95b02SDimitry Andric   // Iterate as long as defined lanes/used lanes keep changing.
5073ca95b02SDimitry Andric   while (!Worklist.empty()) {
5083ca95b02SDimitry Andric     unsigned RegIdx = Worklist.front();
5093ca95b02SDimitry Andric     Worklist.pop_front();
5103ca95b02SDimitry Andric     WorklistMembers.reset(RegIdx);
5113ca95b02SDimitry Andric     VRegInfo &Info = VRegInfos[RegIdx];
5123ca95b02SDimitry Andric     unsigned Reg = TargetRegisterInfo::index2VirtReg(RegIdx);
5133ca95b02SDimitry Andric 
5143ca95b02SDimitry Andric     // Transfer UsedLanes to operands of DefMI (backwards dataflow).
5153ca95b02SDimitry Andric     MachineOperand &Def = *MRI->def_begin(Reg);
5163ca95b02SDimitry Andric     const MachineInstr &MI = *Def.getParent();
5173ca95b02SDimitry Andric     transferUsedLanesStep(MI, Info.UsedLanes);
5183ca95b02SDimitry Andric     // Transfer DefinedLanes to users of Reg (forward dataflow).
5193ca95b02SDimitry Andric     for (const MachineOperand &MO : MRI->use_nodbg_operands(Reg))
5203ca95b02SDimitry Andric       transferDefinedLanesStep(MO, Info.DefinedLanes);
5213ca95b02SDimitry Andric   }
5223ca95b02SDimitry Andric 
523*4ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "Defined/Used lanes:\n"; for (unsigned RegIdx = 0;
524*4ba319b5SDimitry Andric                                                      RegIdx < NumVirtRegs;
525*4ba319b5SDimitry Andric                                                      ++RegIdx) {
5263ca95b02SDimitry Andric     unsigned Reg = TargetRegisterInfo::index2VirtReg(RegIdx);
5273ca95b02SDimitry Andric     const VRegInfo &Info = VRegInfos[RegIdx];
5282cab237bSDimitry Andric     dbgs() << printReg(Reg, nullptr)
5293ca95b02SDimitry Andric            << " Used: " << PrintLaneMask(Info.UsedLanes)
5303ca95b02SDimitry Andric            << " Def: " << PrintLaneMask(Info.DefinedLanes) << '\n';
531*4ba319b5SDimitry Andric   } dbgs() << "\n";);
5323ca95b02SDimitry Andric 
5333ca95b02SDimitry Andric   bool Again = false;
5343ca95b02SDimitry Andric   // Mark operands as dead/unused.
5353ca95b02SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
5363ca95b02SDimitry Andric     for (MachineInstr &MI : MBB) {
5373ca95b02SDimitry Andric       for (MachineOperand &MO : MI.operands()) {
5383ca95b02SDimitry Andric         if (!MO.isReg())
5393ca95b02SDimitry Andric           continue;
5403ca95b02SDimitry Andric         unsigned Reg = MO.getReg();
5413ca95b02SDimitry Andric         if (!TargetRegisterInfo::isVirtualRegister(Reg))
5423ca95b02SDimitry Andric           continue;
5433ca95b02SDimitry Andric         unsigned RegIdx = TargetRegisterInfo::virtReg2Index(Reg);
5443ca95b02SDimitry Andric         const VRegInfo &RegInfo = VRegInfos[RegIdx];
545d88c1a5aSDimitry Andric         if (MO.isDef() && !MO.isDead() && RegInfo.UsedLanes.none()) {
546*4ba319b5SDimitry Andric           LLVM_DEBUG(dbgs()
547*4ba319b5SDimitry Andric                      << "Marking operand '" << MO << "' as dead in " << MI);
5483ca95b02SDimitry Andric           MO.setIsDead();
5493ca95b02SDimitry Andric         }
5503ca95b02SDimitry Andric         if (MO.readsReg()) {
5513ca95b02SDimitry Andric           bool CrossCopy = false;
5523ca95b02SDimitry Andric           if (isUndefRegAtInput(MO, RegInfo)) {
553*4ba319b5SDimitry Andric             LLVM_DEBUG(dbgs()
554*4ba319b5SDimitry Andric                        << "Marking operand '" << MO << "' as undef in " << MI);
5553ca95b02SDimitry Andric             MO.setIsUndef();
5563ca95b02SDimitry Andric           } else if (isUndefInput(MO, &CrossCopy)) {
557*4ba319b5SDimitry Andric             LLVM_DEBUG(dbgs()
558*4ba319b5SDimitry Andric                        << "Marking operand '" << MO << "' as undef in " << MI);
5593ca95b02SDimitry Andric             MO.setIsUndef();
5603ca95b02SDimitry Andric             if (CrossCopy)
5613ca95b02SDimitry Andric               Again = true;
5623ca95b02SDimitry Andric           }
5633ca95b02SDimitry Andric         }
5643ca95b02SDimitry Andric       }
5653ca95b02SDimitry Andric     }
5663ca95b02SDimitry Andric   }
5673ca95b02SDimitry Andric 
5683ca95b02SDimitry Andric   return Again;
5693ca95b02SDimitry Andric }
5703ca95b02SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)5713ca95b02SDimitry Andric bool DetectDeadLanes::runOnMachineFunction(MachineFunction &MF) {
5723ca95b02SDimitry Andric   // Don't bother if we won't track subregister liveness later.  This pass is
5733ca95b02SDimitry Andric   // required for correctness if subregister liveness is enabled because the
5743ca95b02SDimitry Andric   // register coalescer cannot deal with hidden dead defs. However without
5753ca95b02SDimitry Andric   // subregister liveness enabled, the expected benefits of this pass are small
5763ca95b02SDimitry Andric   // so we safe the compile time.
577d88c1a5aSDimitry Andric   MRI = &MF.getRegInfo();
578d88c1a5aSDimitry Andric   if (!MRI->subRegLivenessEnabled()) {
579*4ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << "Skipping Detect dead lanes pass\n");
5803ca95b02SDimitry Andric     return false;
5813ca95b02SDimitry Andric   }
5823ca95b02SDimitry Andric 
5833ca95b02SDimitry Andric   TRI = MRI->getTargetRegisterInfo();
5843ca95b02SDimitry Andric 
5853ca95b02SDimitry Andric   unsigned NumVirtRegs = MRI->getNumVirtRegs();
5863ca95b02SDimitry Andric   VRegInfos = new VRegInfo[NumVirtRegs];
5873ca95b02SDimitry Andric   WorklistMembers.resize(NumVirtRegs);
5883ca95b02SDimitry Andric   DefinedByCopy.resize(NumVirtRegs);
5893ca95b02SDimitry Andric 
5903ca95b02SDimitry Andric   bool Again;
5913ca95b02SDimitry Andric   do {
5923ca95b02SDimitry Andric     Again = runOnce(MF);
5933ca95b02SDimitry Andric   } while(Again);
5943ca95b02SDimitry Andric 
5953ca95b02SDimitry Andric   DefinedByCopy.clear();
5963ca95b02SDimitry Andric   WorklistMembers.clear();
5973ca95b02SDimitry Andric   delete[] VRegInfos;
5983ca95b02SDimitry Andric   return true;
5993ca95b02SDimitry Andric }
600