1fbe85ae1SMatthias Braun //===- DetectDeadLanes.cpp - SubRegister Lane Usage Analysis --*- C++ -*---===//
2fbe85ae1SMatthias Braun //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fbe85ae1SMatthias Braun //
7fbe85ae1SMatthias Braun //===----------------------------------------------------------------------===//
8fbe85ae1SMatthias Braun //
9fbe85ae1SMatthias Braun /// \file
10fbe85ae1SMatthias Braun /// Analysis that tracks defined/used subregister lanes across COPY instructions
11fbe85ae1SMatthias Braun /// and instructions that get lowered to a COPY (PHI, REG_SEQUENCE,
12fbe85ae1SMatthias Braun /// INSERT_SUBREG, EXTRACT_SUBREG).
13fbe85ae1SMatthias Braun /// The information is used to detect dead definitions and the usage of
14fbe85ae1SMatthias Braun /// (completely) undefined values and mark the operands as such.
15fbe85ae1SMatthias Braun /// This pass is necessary because the dead/undef status is not obvious anymore
16fbe85ae1SMatthias Braun /// when subregisters are involved.
17fbe85ae1SMatthias Braun ///
18fbe85ae1SMatthias Braun /// Example:
1993ef1458SFrancis Visoiu Mistrih /// %0 = some definition
2093ef1458SFrancis Visoiu Mistrih /// %1 = IMPLICIT_DEF
2193ef1458SFrancis Visoiu Mistrih /// %2 = REG_SEQUENCE %0, sub0, %1, sub1
2293ef1458SFrancis Visoiu Mistrih /// %3 = EXTRACT_SUBREG %2, sub1
2393ef1458SFrancis Visoiu Mistrih /// = use %3
2493ef1458SFrancis Visoiu Mistrih /// The %0 definition is dead and %3 contains an undefined value.
25fbe85ae1SMatthias Braun //
26fbe85ae1SMatthias Braun //===----------------------------------------------------------------------===//
27fbe85ae1SMatthias Braun
28fbe85ae1SMatthias Braun #include "llvm/ADT/BitVector.h"
29fbe85ae1SMatthias Braun #include "llvm/CodeGen/MachineFunctionPass.h"
30fbe85ae1SMatthias Braun #include "llvm/CodeGen/MachineRegisterInfo.h"
31b3bde2eaSDavid Blaikie #include "llvm/CodeGen/TargetRegisterInfo.h"
32fbe85ae1SMatthias Braun #include "llvm/InitializePasses.h"
33fbe85ae1SMatthias Braun #include "llvm/Pass.h"
34fbe85ae1SMatthias Braun #include "llvm/Support/Debug.h"
35fbe85ae1SMatthias Braun #include "llvm/Support/raw_ostream.h"
367e7106d1SSimon Pilgrim #include <deque>
37fbe85ae1SMatthias Braun
38fbe85ae1SMatthias Braun using namespace llvm;
39fbe85ae1SMatthias Braun
40fbe85ae1SMatthias Braun #define DEBUG_TYPE "detect-dead-lanes"
41fbe85ae1SMatthias Braun
42fbe85ae1SMatthias Braun namespace {
43fbe85ae1SMatthias Braun
44fbe85ae1SMatthias Braun /// Contains a bitmask of which lanes of a given virtual register are
45fbe85ae1SMatthias Braun /// defined and which ones are actually used.
46fbe85ae1SMatthias Braun struct VRegInfo {
47fbe85ae1SMatthias Braun LaneBitmask UsedLanes;
48fbe85ae1SMatthias Braun LaneBitmask DefinedLanes;
49fbe85ae1SMatthias Braun };
50fbe85ae1SMatthias Braun
51fbe85ae1SMatthias Braun class DetectDeadLanes : public MachineFunctionPass {
52fbe85ae1SMatthias Braun public:
53fbe85ae1SMatthias Braun bool runOnMachineFunction(MachineFunction &MF) override;
54fbe85ae1SMatthias Braun
55fbe85ae1SMatthias Braun static char ID;
DetectDeadLanes()56fbe85ae1SMatthias Braun DetectDeadLanes() : MachineFunctionPass(ID) {}
57fbe85ae1SMatthias Braun
getPassName() const58117296c0SMehdi Amini StringRef getPassName() const override { return "Detect Dead Lanes"; }
59fbe85ae1SMatthias Braun
getAnalysisUsage(AnalysisUsage & AU) const603698ca23SMatt Arsenault void getAnalysisUsage(AnalysisUsage &AU) const override {
613698ca23SMatt Arsenault AU.setPreservesCFG();
623698ca23SMatt Arsenault MachineFunctionPass::getAnalysisUsage(AU);
633698ca23SMatt Arsenault }
643698ca23SMatt Arsenault
65fbe85ae1SMatthias Braun private:
66fbe85ae1SMatthias Braun /// Add used lane bits on the register used by operand \p MO. This translates
67fbe85ae1SMatthias Braun /// the bitmask based on the operands subregister, and puts the register into
68fbe85ae1SMatthias Braun /// the worklist if any new bits were added.
69fbe85ae1SMatthias Braun void addUsedLanesOnOperand(const MachineOperand &MO, LaneBitmask UsedLanes);
70fbe85ae1SMatthias Braun
71fbe85ae1SMatthias Braun /// Given a bitmask \p UsedLanes for the used lanes on a def output of a
72fbe85ae1SMatthias Braun /// COPY-like instruction determine the lanes used on the use operands
73fbe85ae1SMatthias Braun /// and call addUsedLanesOnOperand() for them.
7422152acfSMatthias Braun void transferUsedLanesStep(const MachineInstr &MI, LaneBitmask UsedLanes);
75fbe85ae1SMatthias Braun
76fbe85ae1SMatthias Braun /// Given a use regiser operand \p Use and a mask of defined lanes, check
778f429eadSMatthias Braun /// if the operand belongs to a lowersToCopies() instruction, transfer the
78fbe85ae1SMatthias Braun /// mask to the def and put the instruction into the worklist.
79fbe85ae1SMatthias Braun void transferDefinedLanesStep(const MachineOperand &Use,
80fbe85ae1SMatthias Braun LaneBitmask DefinedLanes);
81fbe85ae1SMatthias Braun
82fbe85ae1SMatthias Braun /// Given a mask \p DefinedLanes of lanes defined at operand \p OpNum
83fbe85ae1SMatthias Braun /// of COPY-like instruction, determine which lanes are defined at the output
84fbe85ae1SMatthias Braun /// operand \p Def.
85fbe85ae1SMatthias Braun LaneBitmask transferDefinedLanes(const MachineOperand &Def, unsigned OpNum,
868f429eadSMatthias Braun LaneBitmask DefinedLanes) const;
87fbe85ae1SMatthias Braun
8822152acfSMatthias Braun /// Given a mask \p UsedLanes used from the output of instruction \p MI
8922152acfSMatthias Braun /// determine which lanes are used from operand \p MO of this instruction.
9022152acfSMatthias Braun LaneBitmask transferUsedLanes(const MachineInstr &MI, LaneBitmask UsedLanes,
9122152acfSMatthias Braun const MachineOperand &MO) const;
9222152acfSMatthias Braun
93*3c9229c6SJay Foad std::pair<bool, bool> runOnce(MachineFunction &MF);
9422152acfSMatthias Braun
95fbe85ae1SMatthias Braun LaneBitmask determineInitialDefinedLanes(unsigned Reg);
96fbe85ae1SMatthias Braun LaneBitmask determineInitialUsedLanes(unsigned Reg);
97fbe85ae1SMatthias Braun
9822152acfSMatthias Braun bool isUndefRegAtInput(const MachineOperand &MO,
9922152acfSMatthias Braun const VRegInfo &RegInfo) const;
10022152acfSMatthias Braun
10122152acfSMatthias Braun bool isUndefInput(const MachineOperand &MO, bool *CrossCopy) const;
10222152acfSMatthias Braun
103fbe85ae1SMatthias Braun const MachineRegisterInfo *MRI;
104fbe85ae1SMatthias Braun const TargetRegisterInfo *TRI;
105fbe85ae1SMatthias Braun
PutInWorklist(unsigned RegIdx)106fbe85ae1SMatthias Braun void PutInWorklist(unsigned RegIdx) {
107fbe85ae1SMatthias Braun if (WorklistMembers.test(RegIdx))
108fbe85ae1SMatthias Braun return;
109fbe85ae1SMatthias Braun WorklistMembers.set(RegIdx);
110fbe85ae1SMatthias Braun Worklist.push_back(RegIdx);
111fbe85ae1SMatthias Braun }
112fbe85ae1SMatthias Braun
113fbe85ae1SMatthias Braun VRegInfo *VRegInfos;
114fbe85ae1SMatthias Braun /// Worklist containing virtreg indexes.
115fbe85ae1SMatthias Braun std::deque<unsigned> Worklist;
116fbe85ae1SMatthias Braun BitVector WorklistMembers;
117fbe85ae1SMatthias Braun /// This bitvector is set for each vreg index where the vreg is defined
118fbe85ae1SMatthias Braun /// by an instruction where lowersToCopies()==true.
119fbe85ae1SMatthias Braun BitVector DefinedByCopy;
120fbe85ae1SMatthias Braun };
121fbe85ae1SMatthias Braun
122fbe85ae1SMatthias Braun } // end anonymous namespace
123fbe85ae1SMatthias Braun
124fbe85ae1SMatthias Braun char DetectDeadLanes::ID = 0;
125fbe85ae1SMatthias Braun char &llvm::DetectDeadLanesID = DetectDeadLanes::ID;
126fbe85ae1SMatthias Braun
1271527baabSMatthias Braun INITIALIZE_PASS(DetectDeadLanes, DEBUG_TYPE, "Detect Dead Lanes", false, false)
128fbe85ae1SMatthias Braun
129fbe85ae1SMatthias Braun /// Returns true if \p MI will get lowered to a series of COPY instructions.
130fbe85ae1SMatthias Braun /// We call this a COPY-like instruction.
lowersToCopies(const MachineInstr & MI)131fbe85ae1SMatthias Braun static bool lowersToCopies(const MachineInstr &MI) {
132fbe85ae1SMatthias Braun // Note: We could support instructions with MCInstrDesc::isRegSequenceLike(),
133fbe85ae1SMatthias Braun // isExtractSubRegLike(), isInsertSubregLike() in the future even though they
134fbe85ae1SMatthias Braun // are not lowered to a COPY.
135fbe85ae1SMatthias Braun switch (MI.getOpcode()) {
136fbe85ae1SMatthias Braun case TargetOpcode::COPY:
137fbe85ae1SMatthias Braun case TargetOpcode::PHI:
138fbe85ae1SMatthias Braun case TargetOpcode::INSERT_SUBREG:
139fbe85ae1SMatthias Braun case TargetOpcode::REG_SEQUENCE:
140fbe85ae1SMatthias Braun case TargetOpcode::EXTRACT_SUBREG:
141fbe85ae1SMatthias Braun return true;
142fbe85ae1SMatthias Braun }
143fbe85ae1SMatthias Braun return false;
144fbe85ae1SMatthias Braun }
145fbe85ae1SMatthias Braun
isCrossCopy(const MachineRegisterInfo & MRI,const MachineInstr & MI,const TargetRegisterClass * DstRC,const MachineOperand & MO)146fbe85ae1SMatthias Braun static bool isCrossCopy(const MachineRegisterInfo &MRI,
147fbe85ae1SMatthias Braun const MachineInstr &MI,
148fbe85ae1SMatthias Braun const TargetRegisterClass *DstRC,
149fbe85ae1SMatthias Braun const MachineOperand &MO) {
150fbe85ae1SMatthias Braun assert(lowersToCopies(MI));
1510c476111SDaniel Sanders Register SrcReg = MO.getReg();
152fbe85ae1SMatthias Braun const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
153fbe85ae1SMatthias Braun if (DstRC == SrcRC)
154fbe85ae1SMatthias Braun return false;
155fbe85ae1SMatthias Braun
156fbe85ae1SMatthias Braun unsigned SrcSubIdx = MO.getSubReg();
157fbe85ae1SMatthias Braun
158fbe85ae1SMatthias Braun const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
159fbe85ae1SMatthias Braun unsigned DstSubIdx = 0;
160fbe85ae1SMatthias Braun switch (MI.getOpcode()) {
161fbe85ae1SMatthias Braun case TargetOpcode::INSERT_SUBREG:
162fbe85ae1SMatthias Braun if (MI.getOperandNo(&MO) == 2)
163fbe85ae1SMatthias Braun DstSubIdx = MI.getOperand(3).getImm();
164fbe85ae1SMatthias Braun break;
165fbe85ae1SMatthias Braun case TargetOpcode::REG_SEQUENCE: {
166fbe85ae1SMatthias Braun unsigned OpNum = MI.getOperandNo(&MO);
167fbe85ae1SMatthias Braun DstSubIdx = MI.getOperand(OpNum+1).getImm();
168fbe85ae1SMatthias Braun break;
169fbe85ae1SMatthias Braun }
170fbe85ae1SMatthias Braun case TargetOpcode::EXTRACT_SUBREG: {
171fbe85ae1SMatthias Braun unsigned SubReg = MI.getOperand(2).getImm();
172fbe85ae1SMatthias Braun SrcSubIdx = TRI.composeSubRegIndices(SubReg, SrcSubIdx);
173fbe85ae1SMatthias Braun }
174fbe85ae1SMatthias Braun }
175fbe85ae1SMatthias Braun
176fbe85ae1SMatthias Braun unsigned PreA, PreB; // Unused.
177fbe85ae1SMatthias Braun if (SrcSubIdx && DstSubIdx)
178fbe85ae1SMatthias Braun return !TRI.getCommonSuperRegClass(SrcRC, SrcSubIdx, DstRC, DstSubIdx, PreA,
179fbe85ae1SMatthias Braun PreB);
180fbe85ae1SMatthias Braun if (SrcSubIdx)
181fbe85ae1SMatthias Braun return !TRI.getMatchingSuperRegClass(SrcRC, DstRC, SrcSubIdx);
182fbe85ae1SMatthias Braun if (DstSubIdx)
183fbe85ae1SMatthias Braun return !TRI.getMatchingSuperRegClass(DstRC, SrcRC, DstSubIdx);
184fbe85ae1SMatthias Braun return !TRI.getCommonSubClass(SrcRC, DstRC);
185fbe85ae1SMatthias Braun }
186fbe85ae1SMatthias Braun
addUsedLanesOnOperand(const MachineOperand & MO,LaneBitmask UsedLanes)187fbe85ae1SMatthias Braun void DetectDeadLanes::addUsedLanesOnOperand(const MachineOperand &MO,
188fbe85ae1SMatthias Braun LaneBitmask UsedLanes) {
189fbe85ae1SMatthias Braun if (!MO.readsReg())
190fbe85ae1SMatthias Braun return;
1910c476111SDaniel Sanders Register MOReg = MO.getReg();
1922bea69bfSDaniel Sanders if (!Register::isVirtualRegister(MOReg))
193fbe85ae1SMatthias Braun return;
194fbe85ae1SMatthias Braun
195fbe85ae1SMatthias Braun unsigned MOSubReg = MO.getSubReg();
196fbe85ae1SMatthias Braun if (MOSubReg != 0)
197fbe85ae1SMatthias Braun UsedLanes = TRI->composeSubRegIndexLaneMask(MOSubReg, UsedLanes);
198fbe85ae1SMatthias Braun UsedLanes &= MRI->getMaxLaneMaskForVReg(MOReg);
199fbe85ae1SMatthias Braun
2002bea69bfSDaniel Sanders unsigned MORegIdx = Register::virtReg2Index(MOReg);
201fbe85ae1SMatthias Braun VRegInfo &MORegInfo = VRegInfos[MORegIdx];
202fbe85ae1SMatthias Braun LaneBitmask PrevUsedLanes = MORegInfo.UsedLanes;
203fbe85ae1SMatthias Braun // Any change at all?
20491b5cf84SKrzysztof Parzyszek if ((UsedLanes & ~PrevUsedLanes).none())
205fbe85ae1SMatthias Braun return;
206fbe85ae1SMatthias Braun
207fbe85ae1SMatthias Braun // Set UsedLanes and remember instruction for further propagation.
208fbe85ae1SMatthias Braun MORegInfo.UsedLanes = PrevUsedLanes | UsedLanes;
209fbe85ae1SMatthias Braun if (DefinedByCopy.test(MORegIdx))
210fbe85ae1SMatthias Braun PutInWorklist(MORegIdx);
211fbe85ae1SMatthias Braun }
212fbe85ae1SMatthias Braun
transferUsedLanesStep(const MachineInstr & MI,LaneBitmask UsedLanes)21322152acfSMatthias Braun void DetectDeadLanes::transferUsedLanesStep(const MachineInstr &MI,
214fbe85ae1SMatthias Braun LaneBitmask UsedLanes) {
21522152acfSMatthias Braun for (const MachineOperand &MO : MI.uses()) {
2162bea69bfSDaniel Sanders if (!MO.isReg() || !Register::isVirtualRegister(MO.getReg()))
21722152acfSMatthias Braun continue;
21822152acfSMatthias Braun LaneBitmask UsedOnMO = transferUsedLanes(MI, UsedLanes, MO);
21922152acfSMatthias Braun addUsedLanesOnOperand(MO, UsedOnMO);
22022152acfSMatthias Braun }
22122152acfSMatthias Braun }
22222152acfSMatthias Braun
transferUsedLanes(const MachineInstr & MI,LaneBitmask UsedLanes,const MachineOperand & MO) const22322152acfSMatthias Braun LaneBitmask DetectDeadLanes::transferUsedLanes(const MachineInstr &MI,
22422152acfSMatthias Braun LaneBitmask UsedLanes,
22522152acfSMatthias Braun const MachineOperand &MO) const {
22622152acfSMatthias Braun unsigned OpNum = MI.getOperandNo(&MO);
2272bea69bfSDaniel Sanders assert(lowersToCopies(MI) &&
2282bea69bfSDaniel Sanders DefinedByCopy[Register::virtReg2Index(MI.getOperand(0).getReg())]);
22922152acfSMatthias Braun
230fbe85ae1SMatthias Braun switch (MI.getOpcode()) {
231fbe85ae1SMatthias Braun case TargetOpcode::COPY:
232fbe85ae1SMatthias Braun case TargetOpcode::PHI:
23322152acfSMatthias Braun return UsedLanes;
234fbe85ae1SMatthias Braun case TargetOpcode::REG_SEQUENCE: {
23522152acfSMatthias Braun assert(OpNum % 2 == 1);
23622152acfSMatthias Braun unsigned SubIdx = MI.getOperand(OpNum + 1).getImm();
23722152acfSMatthias Braun return TRI->reverseComposeSubRegIndexLaneMask(SubIdx, UsedLanes);
238fbe85ae1SMatthias Braun }
239fbe85ae1SMatthias Braun case TargetOpcode::INSERT_SUBREG: {
240fbe85ae1SMatthias Braun unsigned SubIdx = MI.getOperand(3).getImm();
241fbe85ae1SMatthias Braun LaneBitmask MO2UsedLanes =
242fbe85ae1SMatthias Braun TRI->reverseComposeSubRegIndexLaneMask(SubIdx, UsedLanes);
24322152acfSMatthias Braun if (OpNum == 2)
24422152acfSMatthias Braun return MO2UsedLanes;
245fbe85ae1SMatthias Braun
24622152acfSMatthias Braun const MachineOperand &Def = MI.getOperand(0);
2470c476111SDaniel Sanders Register DefReg = Def.getReg();
248fbe85ae1SMatthias Braun const TargetRegisterClass *RC = MRI->getRegClass(DefReg);
249fbe85ae1SMatthias Braun LaneBitmask MO1UsedLanes;
250fbe85ae1SMatthias Braun if (RC->CoveredBySubRegs)
251fbe85ae1SMatthias Braun MO1UsedLanes = UsedLanes & ~TRI->getSubRegIndexLaneMask(SubIdx);
252fbe85ae1SMatthias Braun else
253fbe85ae1SMatthias Braun MO1UsedLanes = RC->LaneMask;
25422152acfSMatthias Braun
25522152acfSMatthias Braun assert(OpNum == 1);
25622152acfSMatthias Braun return MO1UsedLanes;
257fbe85ae1SMatthias Braun }
258fbe85ae1SMatthias Braun case TargetOpcode::EXTRACT_SUBREG: {
25922152acfSMatthias Braun assert(OpNum == 1);
260fbe85ae1SMatthias Braun unsigned SubIdx = MI.getOperand(2).getImm();
26122152acfSMatthias Braun return TRI->composeSubRegIndexLaneMask(SubIdx, UsedLanes);
262fbe85ae1SMatthias Braun }
263fbe85ae1SMatthias Braun default:
264fbe85ae1SMatthias Braun llvm_unreachable("function must be called with COPY-like instruction");
265fbe85ae1SMatthias Braun }
266fbe85ae1SMatthias Braun }
267fbe85ae1SMatthias Braun
transferDefinedLanesStep(const MachineOperand & Use,LaneBitmask DefinedLanes)268fbe85ae1SMatthias Braun void DetectDeadLanes::transferDefinedLanesStep(const MachineOperand &Use,
269fbe85ae1SMatthias Braun LaneBitmask DefinedLanes) {
270fbe85ae1SMatthias Braun if (!Use.readsReg())
271fbe85ae1SMatthias Braun return;
272fbe85ae1SMatthias Braun // Check whether the operand writes a vreg and is part of a COPY-like
273fbe85ae1SMatthias Braun // instruction.
274fbe85ae1SMatthias Braun const MachineInstr &MI = *Use.getParent();
275fbe85ae1SMatthias Braun if (MI.getDesc().getNumDefs() != 1)
276fbe85ae1SMatthias Braun return;
277fbe85ae1SMatthias Braun // FIXME: PATCHPOINT instructions announce a Def that does not always exist,
278fbe85ae1SMatthias Braun // they really need to be modeled differently!
279fbe85ae1SMatthias Braun if (MI.getOpcode() == TargetOpcode::PATCHPOINT)
280fbe85ae1SMatthias Braun return;
281fbe85ae1SMatthias Braun const MachineOperand &Def = *MI.defs().begin();
2820c476111SDaniel Sanders Register DefReg = Def.getReg();
2832bea69bfSDaniel Sanders if (!Register::isVirtualRegister(DefReg))
284fbe85ae1SMatthias Braun return;
2852bea69bfSDaniel Sanders unsigned DefRegIdx = Register::virtReg2Index(DefReg);
286fbe85ae1SMatthias Braun if (!DefinedByCopy.test(DefRegIdx))
287fbe85ae1SMatthias Braun return;
288fbe85ae1SMatthias Braun
289fbe85ae1SMatthias Braun unsigned OpNum = MI.getOperandNo(&Use);
290fbe85ae1SMatthias Braun DefinedLanes =
291fbe85ae1SMatthias Braun TRI->reverseComposeSubRegIndexLaneMask(Use.getSubReg(), DefinedLanes);
292fbe85ae1SMatthias Braun DefinedLanes = transferDefinedLanes(Def, OpNum, DefinedLanes);
293fbe85ae1SMatthias Braun
294fbe85ae1SMatthias Braun VRegInfo &RegInfo = VRegInfos[DefRegIdx];
295fbe85ae1SMatthias Braun LaneBitmask PrevDefinedLanes = RegInfo.DefinedLanes;
296fbe85ae1SMatthias Braun // Any change at all?
29791b5cf84SKrzysztof Parzyszek if ((DefinedLanes & ~PrevDefinedLanes).none())
298fbe85ae1SMatthias Braun return;
299fbe85ae1SMatthias Braun
300fbe85ae1SMatthias Braun RegInfo.DefinedLanes = PrevDefinedLanes | DefinedLanes;
301fbe85ae1SMatthias Braun PutInWorklist(DefRegIdx);
302fbe85ae1SMatthias Braun }
303fbe85ae1SMatthias Braun
transferDefinedLanes(const MachineOperand & Def,unsigned OpNum,LaneBitmask DefinedLanes) const304fbe85ae1SMatthias Braun LaneBitmask DetectDeadLanes::transferDefinedLanes(const MachineOperand &Def,
3058f429eadSMatthias Braun unsigned OpNum, LaneBitmask DefinedLanes) const {
306fbe85ae1SMatthias Braun const MachineInstr &MI = *Def.getParent();
307fbe85ae1SMatthias Braun // Translate DefinedLanes if necessary.
308fbe85ae1SMatthias Braun switch (MI.getOpcode()) {
309fbe85ae1SMatthias Braun case TargetOpcode::REG_SEQUENCE: {
310fbe85ae1SMatthias Braun unsigned SubIdx = MI.getOperand(OpNum + 1).getImm();
311fbe85ae1SMatthias Braun DefinedLanes = TRI->composeSubRegIndexLaneMask(SubIdx, DefinedLanes);
312fbe85ae1SMatthias Braun DefinedLanes &= TRI->getSubRegIndexLaneMask(SubIdx);
313fbe85ae1SMatthias Braun break;
314fbe85ae1SMatthias Braun }
315fbe85ae1SMatthias Braun case TargetOpcode::INSERT_SUBREG: {
316fbe85ae1SMatthias Braun unsigned SubIdx = MI.getOperand(3).getImm();
317fbe85ae1SMatthias Braun if (OpNum == 2) {
318fbe85ae1SMatthias Braun DefinedLanes = TRI->composeSubRegIndexLaneMask(SubIdx, DefinedLanes);
319fbe85ae1SMatthias Braun DefinedLanes &= TRI->getSubRegIndexLaneMask(SubIdx);
320fbe85ae1SMatthias Braun } else {
321fbe85ae1SMatthias Braun assert(OpNum == 1 && "INSERT_SUBREG must have two operands");
322fbe85ae1SMatthias Braun // Ignore lanes defined by operand 2.
323fbe85ae1SMatthias Braun DefinedLanes &= ~TRI->getSubRegIndexLaneMask(SubIdx);
324fbe85ae1SMatthias Braun }
325fbe85ae1SMatthias Braun break;
326fbe85ae1SMatthias Braun }
327fbe85ae1SMatthias Braun case TargetOpcode::EXTRACT_SUBREG: {
328fbe85ae1SMatthias Braun unsigned SubIdx = MI.getOperand(2).getImm();
329fbe85ae1SMatthias Braun assert(OpNum == 1 && "EXTRACT_SUBREG must have one register operand only");
330fbe85ae1SMatthias Braun DefinedLanes = TRI->reverseComposeSubRegIndexLaneMask(SubIdx, DefinedLanes);
331fbe85ae1SMatthias Braun break;
332fbe85ae1SMatthias Braun }
333fbe85ae1SMatthias Braun case TargetOpcode::COPY:
334fbe85ae1SMatthias Braun case TargetOpcode::PHI:
335fbe85ae1SMatthias Braun break;
336fbe85ae1SMatthias Braun default:
337fbe85ae1SMatthias Braun llvm_unreachable("function must be called with COPY-like instruction");
338fbe85ae1SMatthias Braun }
339fbe85ae1SMatthias Braun
3408f429eadSMatthias Braun assert(Def.getSubReg() == 0 &&
3418f429eadSMatthias Braun "Should not have subregister defs in machine SSA phase");
342fbe85ae1SMatthias Braun DefinedLanes &= MRI->getMaxLaneMaskForVReg(Def.getReg());
343fbe85ae1SMatthias Braun return DefinedLanes;
344fbe85ae1SMatthias Braun }
345fbe85ae1SMatthias Braun
determineInitialDefinedLanes(unsigned Reg)346fbe85ae1SMatthias Braun LaneBitmask DetectDeadLanes::determineInitialDefinedLanes(unsigned Reg) {
347fbe85ae1SMatthias Braun // Live-In or unused registers have no definition but are considered fully
348fbe85ae1SMatthias Braun // defined.
349fbe85ae1SMatthias Braun if (!MRI->hasOneDef(Reg))
35091b5cf84SKrzysztof Parzyszek return LaneBitmask::getAll();
351fbe85ae1SMatthias Braun
352fbe85ae1SMatthias Braun const MachineOperand &Def = *MRI->def_begin(Reg);
353fbe85ae1SMatthias Braun const MachineInstr &DefMI = *Def.getParent();
354fbe85ae1SMatthias Braun if (lowersToCopies(DefMI)) {
355fbe85ae1SMatthias Braun // Start optimisatically with no used or defined lanes for copy
356fbe85ae1SMatthias Braun // instructions. The following dataflow analysis will add more bits.
3572bea69bfSDaniel Sanders unsigned RegIdx = Register::virtReg2Index(Reg);
358fbe85ae1SMatthias Braun DefinedByCopy.set(RegIdx);
359fbe85ae1SMatthias Braun PutInWorklist(RegIdx);
360fbe85ae1SMatthias Braun
361fbe85ae1SMatthias Braun if (Def.isDead())
36291b5cf84SKrzysztof Parzyszek return LaneBitmask::getNone();
363fbe85ae1SMatthias Braun
364fbe85ae1SMatthias Braun // COPY/PHI can copy across unrelated register classes (example: float/int)
365fbe85ae1SMatthias Braun // with incompatible subregister structure. Do not include these in the
366fbe85ae1SMatthias Braun // dataflow analysis since we cannot transfer lanemasks in a meaningful way.
367fbe85ae1SMatthias Braun const TargetRegisterClass *DefRC = MRI->getRegClass(Reg);
368fbe85ae1SMatthias Braun
369fbe85ae1SMatthias Braun // Determine initially DefinedLanes.
37091b5cf84SKrzysztof Parzyszek LaneBitmask DefinedLanes;
371fbe85ae1SMatthias Braun for (const MachineOperand &MO : DefMI.uses()) {
372fbe85ae1SMatthias Braun if (!MO.isReg() || !MO.readsReg())
373fbe85ae1SMatthias Braun continue;
3740c476111SDaniel Sanders Register MOReg = MO.getReg();
375fbe85ae1SMatthias Braun if (!MOReg)
376fbe85ae1SMatthias Braun continue;
377fbe85ae1SMatthias Braun
378fbe85ae1SMatthias Braun LaneBitmask MODefinedLanes;
3792bea69bfSDaniel Sanders if (Register::isPhysicalRegister(MOReg)) {
38091b5cf84SKrzysztof Parzyszek MODefinedLanes = LaneBitmask::getAll();
381fbe85ae1SMatthias Braun } else if (isCrossCopy(*MRI, DefMI, DefRC, MO)) {
38291b5cf84SKrzysztof Parzyszek MODefinedLanes = LaneBitmask::getAll();
383fbe85ae1SMatthias Braun } else {
3842bea69bfSDaniel Sanders assert(Register::isVirtualRegister(MOReg));
385fbe85ae1SMatthias Braun if (MRI->hasOneDef(MOReg)) {
386fbe85ae1SMatthias Braun const MachineOperand &MODef = *MRI->def_begin(MOReg);
387fbe85ae1SMatthias Braun const MachineInstr &MODefMI = *MODef.getParent();
388fbe85ae1SMatthias Braun // Bits from copy-like operations will be added later.
389fbe85ae1SMatthias Braun if (lowersToCopies(MODefMI) || MODefMI.isImplicitDef())
390fbe85ae1SMatthias Braun continue;
391fbe85ae1SMatthias Braun }
392fbe85ae1SMatthias Braun unsigned MOSubReg = MO.getSubReg();
393fbe85ae1SMatthias Braun MODefinedLanes = MRI->getMaxLaneMaskForVReg(MOReg);
394fbe85ae1SMatthias Braun MODefinedLanes = TRI->reverseComposeSubRegIndexLaneMask(
395fbe85ae1SMatthias Braun MOSubReg, MODefinedLanes);
396fbe85ae1SMatthias Braun }
397fbe85ae1SMatthias Braun
398fbe85ae1SMatthias Braun unsigned OpNum = DefMI.getOperandNo(&MO);
399fbe85ae1SMatthias Braun DefinedLanes |= transferDefinedLanes(Def, OpNum, MODefinedLanes);
400fbe85ae1SMatthias Braun }
401fbe85ae1SMatthias Braun return DefinedLanes;
402fbe85ae1SMatthias Braun }
403fbe85ae1SMatthias Braun if (DefMI.isImplicitDef() || Def.isDead())
40491b5cf84SKrzysztof Parzyszek return LaneBitmask::getNone();
405fbe85ae1SMatthias Braun
4068f429eadSMatthias Braun assert(Def.getSubReg() == 0 &&
4078f429eadSMatthias Braun "Should not have subregister defs in machine SSA phase");
4088f429eadSMatthias Braun return MRI->getMaxLaneMaskForVReg(Reg);
409fbe85ae1SMatthias Braun }
410fbe85ae1SMatthias Braun
determineInitialUsedLanes(unsigned Reg)411fbe85ae1SMatthias Braun LaneBitmask DetectDeadLanes::determineInitialUsedLanes(unsigned Reg) {
41291b5cf84SKrzysztof Parzyszek LaneBitmask UsedLanes = LaneBitmask::getNone();
413fbe85ae1SMatthias Braun for (const MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
414fbe85ae1SMatthias Braun if (!MO.readsReg())
415fbe85ae1SMatthias Braun continue;
416fbe85ae1SMatthias Braun
417fbe85ae1SMatthias Braun const MachineInstr &UseMI = *MO.getParent();
418fbe85ae1SMatthias Braun if (UseMI.isKill())
419fbe85ae1SMatthias Braun continue;
420fbe85ae1SMatthias Braun
421fbe85ae1SMatthias Braun unsigned SubReg = MO.getSubReg();
422fbe85ae1SMatthias Braun if (lowersToCopies(UseMI)) {
423fbe85ae1SMatthias Braun assert(UseMI.getDesc().getNumDefs() == 1);
424fbe85ae1SMatthias Braun const MachineOperand &Def = *UseMI.defs().begin();
4250c476111SDaniel Sanders Register DefReg = Def.getReg();
426fbe85ae1SMatthias Braun // The used lanes of COPY-like instruction operands are determined by the
427fbe85ae1SMatthias Braun // following dataflow analysis.
4282bea69bfSDaniel Sanders if (Register::isVirtualRegister(DefReg)) {
429fbe85ae1SMatthias Braun // But ignore copies across incompatible register classes.
430fbe85ae1SMatthias Braun bool CrossCopy = false;
431fbe85ae1SMatthias Braun if (lowersToCopies(UseMI)) {
432fbe85ae1SMatthias Braun const TargetRegisterClass *DstRC = MRI->getRegClass(DefReg);
433fbe85ae1SMatthias Braun CrossCopy = isCrossCopy(*MRI, UseMI, DstRC, MO);
43422152acfSMatthias Braun if (CrossCopy)
435d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Copy across incompatible classes: " << UseMI);
436fbe85ae1SMatthias Braun }
437fbe85ae1SMatthias Braun
438fbe85ae1SMatthias Braun if (!CrossCopy)
439fbe85ae1SMatthias Braun continue;
440fbe85ae1SMatthias Braun }
441fbe85ae1SMatthias Braun }
442fbe85ae1SMatthias Braun
443fbe85ae1SMatthias Braun // Shortcut: All lanes are used.
444fbe85ae1SMatthias Braun if (SubReg == 0)
445fbe85ae1SMatthias Braun return MRI->getMaxLaneMaskForVReg(Reg);
446fbe85ae1SMatthias Braun
447fbe85ae1SMatthias Braun UsedLanes |= TRI->getSubRegIndexLaneMask(SubReg);
448fbe85ae1SMatthias Braun }
449fbe85ae1SMatthias Braun return UsedLanes;
450fbe85ae1SMatthias Braun }
451fbe85ae1SMatthias Braun
isUndefRegAtInput(const MachineOperand & MO,const VRegInfo & RegInfo) const45222152acfSMatthias Braun bool DetectDeadLanes::isUndefRegAtInput(const MachineOperand &MO,
45322152acfSMatthias Braun const VRegInfo &RegInfo) const {
45422152acfSMatthias Braun unsigned SubReg = MO.getSubReg();
45522152acfSMatthias Braun LaneBitmask Mask = TRI->getSubRegIndexLaneMask(SubReg);
45691b5cf84SKrzysztof Parzyszek return (RegInfo.DefinedLanes & RegInfo.UsedLanes & Mask).none();
45722152acfSMatthias Braun }
45822152acfSMatthias Braun
isUndefInput(const MachineOperand & MO,bool * CrossCopy) const45922152acfSMatthias Braun bool DetectDeadLanes::isUndefInput(const MachineOperand &MO,
46022152acfSMatthias Braun bool *CrossCopy) const {
46122152acfSMatthias Braun if (!MO.isUse())
46222152acfSMatthias Braun return false;
46322152acfSMatthias Braun const MachineInstr &MI = *MO.getParent();
46422152acfSMatthias Braun if (!lowersToCopies(MI))
46522152acfSMatthias Braun return false;
46622152acfSMatthias Braun const MachineOperand &Def = MI.getOperand(0);
4670c476111SDaniel Sanders Register DefReg = Def.getReg();
4682bea69bfSDaniel Sanders if (!Register::isVirtualRegister(DefReg))
46922152acfSMatthias Braun return false;
4702bea69bfSDaniel Sanders unsigned DefRegIdx = Register::virtReg2Index(DefReg);
47122152acfSMatthias Braun if (!DefinedByCopy.test(DefRegIdx))
47222152acfSMatthias Braun return false;
47322152acfSMatthias Braun
47422152acfSMatthias Braun const VRegInfo &DefRegInfo = VRegInfos[DefRegIdx];
47522152acfSMatthias Braun LaneBitmask UsedLanes = transferUsedLanes(MI, DefRegInfo.UsedLanes, MO);
476ea9f8ce0SKrzysztof Parzyszek if (UsedLanes.any())
47722152acfSMatthias Braun return false;
47822152acfSMatthias Braun
4790c476111SDaniel Sanders Register MOReg = MO.getReg();
4802bea69bfSDaniel Sanders if (Register::isVirtualRegister(MOReg)) {
48122152acfSMatthias Braun const TargetRegisterClass *DstRC = MRI->getRegClass(DefReg);
48222152acfSMatthias Braun *CrossCopy = isCrossCopy(*MRI, MI, DstRC, MO);
48322152acfSMatthias Braun }
48422152acfSMatthias Braun return true;
48522152acfSMatthias Braun }
48622152acfSMatthias Braun
runOnce(MachineFunction & MF)487*3c9229c6SJay Foad std::pair<bool, bool> DetectDeadLanes::runOnce(MachineFunction &MF) {
48822152acfSMatthias Braun // First pass: Populate defs/uses of vregs with initial values
48922152acfSMatthias Braun unsigned NumVirtRegs = MRI->getNumVirtRegs();
49022152acfSMatthias Braun for (unsigned RegIdx = 0; RegIdx < NumVirtRegs; ++RegIdx) {
4912bea69bfSDaniel Sanders unsigned Reg = Register::index2VirtReg(RegIdx);
49222152acfSMatthias Braun
49322152acfSMatthias Braun // Determine used/defined lanes and add copy instructions to worklist.
49422152acfSMatthias Braun VRegInfo &Info = VRegInfos[RegIdx];
49522152acfSMatthias Braun Info.DefinedLanes = determineInitialDefinedLanes(Reg);
49622152acfSMatthias Braun Info.UsedLanes = determineInitialUsedLanes(Reg);
49722152acfSMatthias Braun }
49822152acfSMatthias Braun
49922152acfSMatthias Braun // Iterate as long as defined lanes/used lanes keep changing.
50022152acfSMatthias Braun while (!Worklist.empty()) {
50122152acfSMatthias Braun unsigned RegIdx = Worklist.front();
50222152acfSMatthias Braun Worklist.pop_front();
50322152acfSMatthias Braun WorklistMembers.reset(RegIdx);
50422152acfSMatthias Braun VRegInfo &Info = VRegInfos[RegIdx];
5052bea69bfSDaniel Sanders unsigned Reg = Register::index2VirtReg(RegIdx);
50622152acfSMatthias Braun
50722152acfSMatthias Braun // Transfer UsedLanes to operands of DefMI (backwards dataflow).
50822152acfSMatthias Braun MachineOperand &Def = *MRI->def_begin(Reg);
50922152acfSMatthias Braun const MachineInstr &MI = *Def.getParent();
51022152acfSMatthias Braun transferUsedLanesStep(MI, Info.UsedLanes);
51122152acfSMatthias Braun // Transfer DefinedLanes to users of Reg (forward dataflow).
51222152acfSMatthias Braun for (const MachineOperand &MO : MRI->use_nodbg_operands(Reg))
51322152acfSMatthias Braun transferDefinedLanesStep(MO, Info.DefinedLanes);
51422152acfSMatthias Braun }
51522152acfSMatthias Braun
516e00d67dcSDavid Green LLVM_DEBUG({
517e00d67dcSDavid Green dbgs() << "Defined/Used lanes:\n";
518e00d67dcSDavid Green for (unsigned RegIdx = 0; RegIdx < NumVirtRegs; ++RegIdx) {
5192bea69bfSDaniel Sanders unsigned Reg = Register::index2VirtReg(RegIdx);
52022152acfSMatthias Braun const VRegInfo &Info = VRegInfos[RegIdx];
5219d419d3bSFrancis Visoiu Mistrih dbgs() << printReg(Reg, nullptr)
52222152acfSMatthias Braun << " Used: " << PrintLaneMask(Info.UsedLanes)
52322152acfSMatthias Braun << " Def: " << PrintLaneMask(Info.DefinedLanes) << '\n';
524e00d67dcSDavid Green }
525e00d67dcSDavid Green dbgs() << "\n";
526e00d67dcSDavid Green });
52722152acfSMatthias Braun
528*3c9229c6SJay Foad bool Changed = false;
52922152acfSMatthias Braun bool Again = false;
53022152acfSMatthias Braun // Mark operands as dead/unused.
53122152acfSMatthias Braun for (MachineBasicBlock &MBB : MF) {
53222152acfSMatthias Braun for (MachineInstr &MI : MBB) {
53322152acfSMatthias Braun for (MachineOperand &MO : MI.operands()) {
53422152acfSMatthias Braun if (!MO.isReg())
53522152acfSMatthias Braun continue;
5360c476111SDaniel Sanders Register Reg = MO.getReg();
5372bea69bfSDaniel Sanders if (!Register::isVirtualRegister(Reg))
53822152acfSMatthias Braun continue;
5392bea69bfSDaniel Sanders unsigned RegIdx = Register::virtReg2Index(Reg);
54022152acfSMatthias Braun const VRegInfo &RegInfo = VRegInfos[RegIdx];
54191b5cf84SKrzysztof Parzyszek if (MO.isDef() && !MO.isDead() && RegInfo.UsedLanes.none()) {
542d34e60caSNicola Zaghen LLVM_DEBUG(dbgs()
543d34e60caSNicola Zaghen << "Marking operand '" << MO << "' as dead in " << MI);
54422152acfSMatthias Braun MO.setIsDead();
545*3c9229c6SJay Foad Changed = true;
54622152acfSMatthias Braun }
54722152acfSMatthias Braun if (MO.readsReg()) {
54822152acfSMatthias Braun bool CrossCopy = false;
54922152acfSMatthias Braun if (isUndefRegAtInput(MO, RegInfo)) {
550d34e60caSNicola Zaghen LLVM_DEBUG(dbgs()
551d34e60caSNicola Zaghen << "Marking operand '" << MO << "' as undef in " << MI);
55222152acfSMatthias Braun MO.setIsUndef();
553*3c9229c6SJay Foad Changed = true;
55422152acfSMatthias Braun } else if (isUndefInput(MO, &CrossCopy)) {
555d34e60caSNicola Zaghen LLVM_DEBUG(dbgs()
556d34e60caSNicola Zaghen << "Marking operand '" << MO << "' as undef in " << MI);
55722152acfSMatthias Braun MO.setIsUndef();
558*3c9229c6SJay Foad Changed = true;
55922152acfSMatthias Braun if (CrossCopy)
56022152acfSMatthias Braun Again = true;
56122152acfSMatthias Braun }
56222152acfSMatthias Braun }
56322152acfSMatthias Braun }
56422152acfSMatthias Braun }
56522152acfSMatthias Braun }
56622152acfSMatthias Braun
567*3c9229c6SJay Foad return std::make_pair(Changed, Again);
56822152acfSMatthias Braun }
56922152acfSMatthias Braun
runOnMachineFunction(MachineFunction & MF)570fbe85ae1SMatthias Braun bool DetectDeadLanes::runOnMachineFunction(MachineFunction &MF) {
571fbe85ae1SMatthias Braun // Don't bother if we won't track subregister liveness later. This pass is
572fbe85ae1SMatthias Braun // required for correctness if subregister liveness is enabled because the
573fbe85ae1SMatthias Braun // register coalescer cannot deal with hidden dead defs. However without
574fbe85ae1SMatthias Braun // subregister liveness enabled, the expected benefits of this pass are small
575fbe85ae1SMatthias Braun // so we safe the compile time.
576f1b20c52SMatthias Braun MRI = &MF.getRegInfo();
577f1b20c52SMatthias Braun if (!MRI->subRegLivenessEnabled()) {
578d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Skipping Detect dead lanes pass\n");
579fbe85ae1SMatthias Braun return false;
580fbe85ae1SMatthias Braun }
581fbe85ae1SMatthias Braun
582fbe85ae1SMatthias Braun TRI = MRI->getTargetRegisterInfo();
583fbe85ae1SMatthias Braun
584fbe85ae1SMatthias Braun unsigned NumVirtRegs = MRI->getNumVirtRegs();
585fbe85ae1SMatthias Braun VRegInfos = new VRegInfo[NumVirtRegs];
586fbe85ae1SMatthias Braun WorklistMembers.resize(NumVirtRegs);
587fbe85ae1SMatthias Braun DefinedByCopy.resize(NumVirtRegs);
588fbe85ae1SMatthias Braun
589*3c9229c6SJay Foad bool Changed = false;
59022152acfSMatthias Braun bool Again;
59122152acfSMatthias Braun do {
592*3c9229c6SJay Foad bool LocalChanged;
593*3c9229c6SJay Foad std::tie(LocalChanged, Again) = runOnce(MF);
594*3c9229c6SJay Foad Changed |= LocalChanged;
59522152acfSMatthias Braun } while(Again);
596fbe85ae1SMatthias Braun
597fbe85ae1SMatthias Braun DefinedByCopy.clear();
598fbe85ae1SMatthias Braun WorklistMembers.clear();
599fbe85ae1SMatthias Braun delete[] VRegInfos;
600*3c9229c6SJay Foad return Changed;
601fbe85ae1SMatthias Braun }
602