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