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