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