163faed5bSDimitry Andric //===-- lib/CodeGen/MachineInstrBundle.cpp --------------------------------===//
263faed5bSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
663faed5bSDimitry Andric //
763faed5bSDimitry Andric //===----------------------------------------------------------------------===//
863faed5bSDimitry Andric
963faed5bSDimitry Andric #include "llvm/CodeGen/MachineInstrBundle.h"
104a16efa3SDimitry Andric #include "llvm/ADT/SmallSet.h"
114a16efa3SDimitry Andric #include "llvm/ADT/SmallVector.h"
124a16efa3SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
1363faed5bSDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
1463faed5bSDimitry Andric #include "llvm/CodeGen/Passes.h"
15044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
16044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
17044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
18706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
19145449b1SDimitry Andric #include "llvm/Pass.h"
20145449b1SDimitry Andric #include "llvm/PassRegistry.h"
2101095a5dSDimitry Andric #include <utility>
2263faed5bSDimitry Andric using namespace llvm;
2363faed5bSDimitry Andric
2463faed5bSDimitry Andric namespace {
2563faed5bSDimitry Andric class UnpackMachineBundles : public MachineFunctionPass {
2663faed5bSDimitry Andric public:
2763faed5bSDimitry Andric static char ID; // Pass identification
UnpackMachineBundles(std::function<bool (const MachineFunction &)> Ftor=nullptr)28b915e9e0SDimitry Andric UnpackMachineBundles(
29b915e9e0SDimitry Andric std::function<bool(const MachineFunction &)> Ftor = nullptr)
3001095a5dSDimitry Andric : MachineFunctionPass(ID), PredicateFtor(std::move(Ftor)) {
3163faed5bSDimitry Andric initializeUnpackMachineBundlesPass(*PassRegistry::getPassRegistry());
3263faed5bSDimitry Andric }
3363faed5bSDimitry Andric
345ca98fd9SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
3585d8b2bbSDimitry Andric
3685d8b2bbSDimitry Andric private:
37b915e9e0SDimitry Andric std::function<bool(const MachineFunction &)> PredicateFtor;
3863faed5bSDimitry Andric };
3963faed5bSDimitry Andric } // end anonymous namespace
4063faed5bSDimitry Andric
4163faed5bSDimitry Andric char UnpackMachineBundles::ID = 0;
4263faed5bSDimitry Andric char &llvm::UnpackMachineBundlesID = UnpackMachineBundles::ID;
4363faed5bSDimitry Andric INITIALIZE_PASS(UnpackMachineBundles, "unpack-mi-bundles",
4463faed5bSDimitry Andric "Unpack machine instruction bundles", false, false)
4563faed5bSDimitry Andric
runOnMachineFunction(MachineFunction & MF)4663faed5bSDimitry Andric bool UnpackMachineBundles::runOnMachineFunction(MachineFunction &MF) {
47b915e9e0SDimitry Andric if (PredicateFtor && !PredicateFtor(MF))
4885d8b2bbSDimitry Andric return false;
4985d8b2bbSDimitry Andric
5063faed5bSDimitry Andric bool Changed = false;
51344a3780SDimitry Andric for (MachineBasicBlock &MBB : MF) {
52344a3780SDimitry Andric for (MachineBasicBlock::instr_iterator MII = MBB.instr_begin(),
53344a3780SDimitry Andric MIE = MBB.instr_end(); MII != MIE; ) {
5463faed5bSDimitry Andric MachineInstr *MI = &*MII;
5563faed5bSDimitry Andric
5663faed5bSDimitry Andric // Remove BUNDLE instruction and the InsideBundle flags from bundled
5763faed5bSDimitry Andric // instructions.
5863faed5bSDimitry Andric if (MI->isBundle()) {
594a16efa3SDimitry Andric while (++MII != MIE && MII->isBundledWithPred()) {
604a16efa3SDimitry Andric MII->unbundleFromPred();
617fa27ce4SDimitry Andric for (MachineOperand &MO : MII->operands()) {
6263faed5bSDimitry Andric if (MO.isReg() && MO.isInternalRead())
6363faed5bSDimitry Andric MO.setIsInternalRead(false);
6463faed5bSDimitry Andric }
6563faed5bSDimitry Andric }
6663faed5bSDimitry Andric MI->eraseFromParent();
6763faed5bSDimitry Andric
6863faed5bSDimitry Andric Changed = true;
6963faed5bSDimitry Andric continue;
7063faed5bSDimitry Andric }
7163faed5bSDimitry Andric
7263faed5bSDimitry Andric ++MII;
7363faed5bSDimitry Andric }
7463faed5bSDimitry Andric }
7563faed5bSDimitry Andric
7663faed5bSDimitry Andric return Changed;
7763faed5bSDimitry Andric }
7863faed5bSDimitry Andric
7985d8b2bbSDimitry Andric FunctionPass *
createUnpackMachineBundles(std::function<bool (const MachineFunction &)> Ftor)80b915e9e0SDimitry Andric llvm::createUnpackMachineBundles(
81b915e9e0SDimitry Andric std::function<bool(const MachineFunction &)> Ftor) {
8201095a5dSDimitry Andric return new UnpackMachineBundles(std::move(Ftor));
8385d8b2bbSDimitry Andric }
8463faed5bSDimitry Andric
8563faed5bSDimitry Andric namespace {
8663faed5bSDimitry Andric class FinalizeMachineBundles : public MachineFunctionPass {
8763faed5bSDimitry Andric public:
8863faed5bSDimitry Andric static char ID; // Pass identification
FinalizeMachineBundles()8963faed5bSDimitry Andric FinalizeMachineBundles() : MachineFunctionPass(ID) {
9063faed5bSDimitry Andric initializeFinalizeMachineBundlesPass(*PassRegistry::getPassRegistry());
9163faed5bSDimitry Andric }
9263faed5bSDimitry Andric
935ca98fd9SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
9463faed5bSDimitry Andric };
9563faed5bSDimitry Andric } // end anonymous namespace
9663faed5bSDimitry Andric
9763faed5bSDimitry Andric char FinalizeMachineBundles::ID = 0;
9863faed5bSDimitry Andric char &llvm::FinalizeMachineBundlesID = FinalizeMachineBundles::ID;
9963faed5bSDimitry Andric INITIALIZE_PASS(FinalizeMachineBundles, "finalize-mi-bundles",
10063faed5bSDimitry Andric "Finalize machine instruction bundles", false, false)
10163faed5bSDimitry Andric
runOnMachineFunction(MachineFunction & MF)10263faed5bSDimitry Andric bool FinalizeMachineBundles::runOnMachineFunction(MachineFunction &MF) {
10363faed5bSDimitry Andric return llvm::finalizeBundles(MF);
10463faed5bSDimitry Andric }
10563faed5bSDimitry Andric
106d8e91e46SDimitry Andric /// Return the first found DebugLoc that has a DILocation, given a range of
107d8e91e46SDimitry Andric /// instructions. The search range is from FirstMI to LastMI (exclusive). If no
108d8e91e46SDimitry Andric /// DILocation is found, then an empty location is returned.
getDebugLoc(MachineBasicBlock::instr_iterator FirstMI,MachineBasicBlock::instr_iterator LastMI)109d8e91e46SDimitry Andric static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI,
110d8e91e46SDimitry Andric MachineBasicBlock::instr_iterator LastMI) {
111d8e91e46SDimitry Andric for (auto MII = FirstMI; MII != LastMI; ++MII)
112145449b1SDimitry Andric if (MII->getDebugLoc())
113d8e91e46SDimitry Andric return MII->getDebugLoc();
114d8e91e46SDimitry Andric return DebugLoc();
115d8e91e46SDimitry Andric }
11663faed5bSDimitry Andric
11763faed5bSDimitry Andric /// finalizeBundle - Finalize a machine instruction bundle which includes
11863faed5bSDimitry Andric /// a sequence of instructions starting from FirstMI to LastMI (exclusive).
11963faed5bSDimitry Andric /// This routine adds a BUNDLE instruction to represent the bundle, it adds
12063faed5bSDimitry Andric /// IsInternalRead markers to MachineOperands which are defined inside the
12163faed5bSDimitry Andric /// bundle, and it copies externally visible defs and uses to the BUNDLE
12263faed5bSDimitry Andric /// instruction.
finalizeBundle(MachineBasicBlock & MBB,MachineBasicBlock::instr_iterator FirstMI,MachineBasicBlock::instr_iterator LastMI)12363faed5bSDimitry Andric void llvm::finalizeBundle(MachineBasicBlock &MBB,
12463faed5bSDimitry Andric MachineBasicBlock::instr_iterator FirstMI,
12563faed5bSDimitry Andric MachineBasicBlock::instr_iterator LastMI) {
12663faed5bSDimitry Andric assert(FirstMI != LastMI && "Empty bundle?");
1274a16efa3SDimitry Andric MIBundleBuilder Bundle(MBB, FirstMI, LastMI);
12863faed5bSDimitry Andric
12967c32a98SDimitry Andric MachineFunction &MF = *MBB.getParent();
13067c32a98SDimitry Andric const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
13167c32a98SDimitry Andric const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
13263faed5bSDimitry Andric
13367c32a98SDimitry Andric MachineInstrBuilder MIB =
134d8e91e46SDimitry Andric BuildMI(MF, getDebugLoc(FirstMI, LastMI), TII->get(TargetOpcode::BUNDLE));
1354a16efa3SDimitry Andric Bundle.prepend(MIB);
13663faed5bSDimitry Andric
137cfca06d7SDimitry Andric SmallVector<Register, 32> LocalDefs;
138cfca06d7SDimitry Andric SmallSet<Register, 32> LocalDefSet;
139cfca06d7SDimitry Andric SmallSet<Register, 8> DeadDefSet;
140cfca06d7SDimitry Andric SmallSet<Register, 16> KilledDefSet;
141cfca06d7SDimitry Andric SmallVector<Register, 8> ExternUses;
142cfca06d7SDimitry Andric SmallSet<Register, 8> ExternUseSet;
143cfca06d7SDimitry Andric SmallSet<Register, 8> KilledUseSet;
144cfca06d7SDimitry Andric SmallSet<Register, 8> UndefUseSet;
14563faed5bSDimitry Andric SmallVector<MachineOperand*, 4> Defs;
146d8e91e46SDimitry Andric for (auto MII = FirstMI; MII != LastMI; ++MII) {
1476f8fc217SDimitry Andric // Debug instructions have no effects to track.
1486f8fc217SDimitry Andric if (MII->isDebugInstr())
1496f8fc217SDimitry Andric continue;
1506f8fc217SDimitry Andric
1517fa27ce4SDimitry Andric for (MachineOperand &MO : MII->operands()) {
15263faed5bSDimitry Andric if (!MO.isReg())
15363faed5bSDimitry Andric continue;
15463faed5bSDimitry Andric if (MO.isDef()) {
15563faed5bSDimitry Andric Defs.push_back(&MO);
15663faed5bSDimitry Andric continue;
15763faed5bSDimitry Andric }
15863faed5bSDimitry Andric
1591d5ae102SDimitry Andric Register Reg = MO.getReg();
16063faed5bSDimitry Andric if (!Reg)
16163faed5bSDimitry Andric continue;
1621d5ae102SDimitry Andric
16363faed5bSDimitry Andric if (LocalDefSet.count(Reg)) {
16463faed5bSDimitry Andric MO.setIsInternalRead();
16563faed5bSDimitry Andric if (MO.isKill())
16663faed5bSDimitry Andric // Internal def is now killed.
16763faed5bSDimitry Andric KilledDefSet.insert(Reg);
16863faed5bSDimitry Andric } else {
16967c32a98SDimitry Andric if (ExternUseSet.insert(Reg).second) {
17063faed5bSDimitry Andric ExternUses.push_back(Reg);
17163faed5bSDimitry Andric if (MO.isUndef())
17263faed5bSDimitry Andric UndefUseSet.insert(Reg);
17363faed5bSDimitry Andric }
17463faed5bSDimitry Andric if (MO.isKill())
17563faed5bSDimitry Andric // External def is now killed.
17663faed5bSDimitry Andric KilledUseSet.insert(Reg);
17763faed5bSDimitry Andric }
17863faed5bSDimitry Andric }
17963faed5bSDimitry Andric
180ac9a064cSDimitry Andric for (MachineOperand *MO : Defs) {
181ac9a064cSDimitry Andric Register Reg = MO->getReg();
18263faed5bSDimitry Andric if (!Reg)
18363faed5bSDimitry Andric continue;
18463faed5bSDimitry Andric
18567c32a98SDimitry Andric if (LocalDefSet.insert(Reg).second) {
18663faed5bSDimitry Andric LocalDefs.push_back(Reg);
187ac9a064cSDimitry Andric if (MO->isDead()) {
18863faed5bSDimitry Andric DeadDefSet.insert(Reg);
18963faed5bSDimitry Andric }
19063faed5bSDimitry Andric } else {
19163faed5bSDimitry Andric // Re-defined inside the bundle, it's no longer killed.
19263faed5bSDimitry Andric KilledDefSet.erase(Reg);
193ac9a064cSDimitry Andric if (!MO->isDead())
19463faed5bSDimitry Andric // Previously defined but dead.
19563faed5bSDimitry Andric DeadDefSet.erase(Reg);
19663faed5bSDimitry Andric }
19763faed5bSDimitry Andric
198ac9a064cSDimitry Andric if (!MO->isDead() && Reg.isPhysical()) {
1997fa27ce4SDimitry Andric for (MCPhysReg SubReg : TRI->subregs(Reg)) {
20067c32a98SDimitry Andric if (LocalDefSet.insert(SubReg).second)
20163faed5bSDimitry Andric LocalDefs.push_back(SubReg);
20263faed5bSDimitry Andric }
20363faed5bSDimitry Andric }
20463faed5bSDimitry Andric }
20563faed5bSDimitry Andric
20663faed5bSDimitry Andric Defs.clear();
20763faed5bSDimitry Andric }
20863faed5bSDimitry Andric
209cfca06d7SDimitry Andric SmallSet<Register, 32> Added;
21099aabd70SDimitry Andric for (Register Reg : LocalDefs) {
21167c32a98SDimitry Andric if (Added.insert(Reg).second) {
21263faed5bSDimitry Andric // If it's not live beyond end of the bundle, mark it dead.
21363faed5bSDimitry Andric bool isDead = DeadDefSet.count(Reg) || KilledDefSet.count(Reg);
21463faed5bSDimitry Andric MIB.addReg(Reg, getDefRegState(true) | getDeadRegState(isDead) |
21563faed5bSDimitry Andric getImplRegState(true));
21663faed5bSDimitry Andric }
21763faed5bSDimitry Andric }
21863faed5bSDimitry Andric
21999aabd70SDimitry Andric for (Register Reg : ExternUses) {
22063faed5bSDimitry Andric bool isKill = KilledUseSet.count(Reg);
22163faed5bSDimitry Andric bool isUndef = UndefUseSet.count(Reg);
22263faed5bSDimitry Andric MIB.addReg(Reg, getKillRegState(isKill) | getUndefRegState(isUndef) |
22363faed5bSDimitry Andric getImplRegState(true));
22463faed5bSDimitry Andric }
225d8e91e46SDimitry Andric
226d8e91e46SDimitry Andric // Set FrameSetup/FrameDestroy for the bundle. If any of the instructions got
227d8e91e46SDimitry Andric // the property, then also set it on the bundle.
228d8e91e46SDimitry Andric for (auto MII = FirstMI; MII != LastMI; ++MII) {
229d8e91e46SDimitry Andric if (MII->getFlag(MachineInstr::FrameSetup))
230d8e91e46SDimitry Andric MIB.setMIFlag(MachineInstr::FrameSetup);
231d8e91e46SDimitry Andric if (MII->getFlag(MachineInstr::FrameDestroy))
232d8e91e46SDimitry Andric MIB.setMIFlag(MachineInstr::FrameDestroy);
233d8e91e46SDimitry Andric }
23463faed5bSDimitry Andric }
23563faed5bSDimitry Andric
23663faed5bSDimitry Andric /// finalizeBundle - Same functionality as the previous finalizeBundle except
23763faed5bSDimitry Andric /// the last instruction in the bundle is not provided as an input. This is
23863faed5bSDimitry Andric /// used in cases where bundles are pre-determined by marking instructions
23963faed5bSDimitry Andric /// with 'InsideBundle' marker. It returns the MBB instruction iterator that
24063faed5bSDimitry Andric /// points to the end of the bundle.
24163faed5bSDimitry Andric MachineBasicBlock::instr_iterator
finalizeBundle(MachineBasicBlock & MBB,MachineBasicBlock::instr_iterator FirstMI)24263faed5bSDimitry Andric llvm::finalizeBundle(MachineBasicBlock &MBB,
24363faed5bSDimitry Andric MachineBasicBlock::instr_iterator FirstMI) {
24463faed5bSDimitry Andric MachineBasicBlock::instr_iterator E = MBB.instr_end();
2455ca98fd9SDimitry Andric MachineBasicBlock::instr_iterator LastMI = std::next(FirstMI);
24663faed5bSDimitry Andric while (LastMI != E && LastMI->isInsideBundle())
24763faed5bSDimitry Andric ++LastMI;
24863faed5bSDimitry Andric finalizeBundle(MBB, FirstMI, LastMI);
24963faed5bSDimitry Andric return LastMI;
25063faed5bSDimitry Andric }
25163faed5bSDimitry Andric
25263faed5bSDimitry Andric /// finalizeBundles - Finalize instruction bundles in the specified
25363faed5bSDimitry Andric /// MachineFunction. Return true if any bundles are finalized.
finalizeBundles(MachineFunction & MF)25463faed5bSDimitry Andric bool llvm::finalizeBundles(MachineFunction &MF) {
25563faed5bSDimitry Andric bool Changed = false;
256344a3780SDimitry Andric for (MachineBasicBlock &MBB : MF) {
25763faed5bSDimitry Andric MachineBasicBlock::instr_iterator MII = MBB.instr_begin();
25863faed5bSDimitry Andric MachineBasicBlock::instr_iterator MIE = MBB.instr_end();
25963faed5bSDimitry Andric if (MII == MIE)
26063faed5bSDimitry Andric continue;
2614a16efa3SDimitry Andric assert(!MII->isInsideBundle() &&
2624a16efa3SDimitry Andric "First instr cannot be inside bundle before finalization!");
2634a16efa3SDimitry Andric
26463faed5bSDimitry Andric for (++MII; MII != MIE; ) {
26563faed5bSDimitry Andric if (!MII->isInsideBundle())
26663faed5bSDimitry Andric ++MII;
26763faed5bSDimitry Andric else {
2685ca98fd9SDimitry Andric MII = finalizeBundle(MBB, std::prev(MII));
26963faed5bSDimitry Andric Changed = true;
27063faed5bSDimitry Andric }
27163faed5bSDimitry Andric }
27263faed5bSDimitry Andric }
27363faed5bSDimitry Andric
27463faed5bSDimitry Andric return Changed;
27563faed5bSDimitry Andric }
27663faed5bSDimitry Andric
AnalyzeVirtRegInBundle(MachineInstr & MI,Register Reg,SmallVectorImpl<std::pair<MachineInstr *,unsigned>> * Ops)277706b4fc4SDimitry Andric VirtRegInfo llvm::AnalyzeVirtRegInBundle(
278cfca06d7SDimitry Andric MachineInstr &MI, Register Reg,
27963faed5bSDimitry Andric SmallVectorImpl<std::pair<MachineInstr *, unsigned>> *Ops) {
280522600a2SDimitry Andric VirtRegInfo RI = {false, false, false};
281706b4fc4SDimitry Andric for (MIBundleOperands O(MI); O.isValid(); ++O) {
282706b4fc4SDimitry Andric MachineOperand &MO = *O;
28363faed5bSDimitry Andric if (!MO.isReg() || MO.getReg() != Reg)
28463faed5bSDimitry Andric continue;
28563faed5bSDimitry Andric
28663faed5bSDimitry Andric // Remember each (MI, OpNo) that refers to Reg.
28763faed5bSDimitry Andric if (Ops)
288706b4fc4SDimitry Andric Ops->push_back(std::make_pair(MO.getParent(), O.getOperandNo()));
28963faed5bSDimitry Andric
29063faed5bSDimitry Andric // Both defs and uses can read virtual registers.
29163faed5bSDimitry Andric if (MO.readsReg()) {
29263faed5bSDimitry Andric RI.Reads = true;
29363faed5bSDimitry Andric if (MO.isDef())
29463faed5bSDimitry Andric RI.Tied = true;
29563faed5bSDimitry Andric }
29663faed5bSDimitry Andric
29763faed5bSDimitry Andric // Only defs can write.
29863faed5bSDimitry Andric if (MO.isDef())
29963faed5bSDimitry Andric RI.Writes = true;
300706b4fc4SDimitry Andric else if (!RI.Tied &&
301706b4fc4SDimitry Andric MO.getParent()->isRegTiedToDefOperand(O.getOperandNo()))
30263faed5bSDimitry Andric RI.Tied = true;
30363faed5bSDimitry Andric }
30463faed5bSDimitry Andric return RI;
30563faed5bSDimitry Andric }
306522600a2SDimitry Andric
3077fa27ce4SDimitry Andric std::pair<LaneBitmask, LaneBitmask>
AnalyzeVirtRegLanesInBundle(const MachineInstr & MI,Register Reg,const MachineRegisterInfo & MRI,const TargetRegisterInfo & TRI)3087fa27ce4SDimitry Andric llvm::AnalyzeVirtRegLanesInBundle(const MachineInstr &MI, Register Reg,
3097fa27ce4SDimitry Andric const MachineRegisterInfo &MRI,
3107fa27ce4SDimitry Andric const TargetRegisterInfo &TRI) {
3117fa27ce4SDimitry Andric
3127fa27ce4SDimitry Andric LaneBitmask UseMask, DefMask;
3137fa27ce4SDimitry Andric
314ac9a064cSDimitry Andric for (const MachineOperand &MO : const_mi_bundle_ops(MI)) {
3157fa27ce4SDimitry Andric if (!MO.isReg() || MO.getReg() != Reg)
3167fa27ce4SDimitry Andric continue;
3177fa27ce4SDimitry Andric
3187fa27ce4SDimitry Andric unsigned SubReg = MO.getSubReg();
3197fa27ce4SDimitry Andric if (SubReg == 0 && MO.isUse() && !MO.isUndef())
3207fa27ce4SDimitry Andric UseMask |= MRI.getMaxLaneMaskForVReg(Reg);
3217fa27ce4SDimitry Andric
3227fa27ce4SDimitry Andric LaneBitmask SubRegMask = TRI.getSubRegIndexLaneMask(SubReg);
3237fa27ce4SDimitry Andric if (MO.isDef()) {
3247fa27ce4SDimitry Andric if (!MO.isUndef())
3257fa27ce4SDimitry Andric UseMask |= ~SubRegMask;
3267fa27ce4SDimitry Andric DefMask |= SubRegMask;
3277fa27ce4SDimitry Andric } else if (!MO.isUndef())
3287fa27ce4SDimitry Andric UseMask |= SubRegMask;
3297fa27ce4SDimitry Andric }
3307fa27ce4SDimitry Andric
3317fa27ce4SDimitry Andric return {UseMask, DefMask};
3327fa27ce4SDimitry Andric }
3337fa27ce4SDimitry Andric
AnalyzePhysRegInBundle(const MachineInstr & MI,Register Reg,const TargetRegisterInfo * TRI)334cfca06d7SDimitry Andric PhysRegInfo llvm::AnalyzePhysRegInBundle(const MachineInstr &MI, Register Reg,
335522600a2SDimitry Andric const TargetRegisterInfo *TRI) {
336522600a2SDimitry Andric bool AllDefsDead = true;
33701095a5dSDimitry Andric PhysRegInfo PRI = {false, false, false, false, false, false, false, false};
338522600a2SDimitry Andric
339cfca06d7SDimitry Andric assert(Reg.isPhysical() && "analyzePhysReg not given a physical register!");
340ac9a064cSDimitry Andric for (const MachineOperand &MO : const_mi_bundle_ops(MI)) {
341dd58ef01SDimitry Andric if (MO.isRegMask() && MO.clobbersPhysReg(Reg)) {
342dd58ef01SDimitry Andric PRI.Clobbered = true;
343dd58ef01SDimitry Andric continue;
344dd58ef01SDimitry Andric }
345522600a2SDimitry Andric
346522600a2SDimitry Andric if (!MO.isReg())
347522600a2SDimitry Andric continue;
348522600a2SDimitry Andric
3491d5ae102SDimitry Andric Register MOReg = MO.getReg();
350e3b55780SDimitry Andric if (!MOReg || !MOReg.isPhysical())
351522600a2SDimitry Andric continue;
352522600a2SDimitry Andric
353dd58ef01SDimitry Andric if (!TRI->regsOverlap(MOReg, Reg))
354522600a2SDimitry Andric continue;
355522600a2SDimitry Andric
3568a6c1c25SDimitry Andric bool Covered = TRI->isSuperRegisterEq(Reg, MOReg);
357dd58ef01SDimitry Andric if (MO.readsReg()) {
358dd58ef01SDimitry Andric PRI.Read = true;
359dd58ef01SDimitry Andric if (Covered) {
360dd58ef01SDimitry Andric PRI.FullyRead = true;
361dd58ef01SDimitry Andric if (MO.isKill())
362dd58ef01SDimitry Andric PRI.Killed = true;
363dd58ef01SDimitry Andric }
364dd58ef01SDimitry Andric } else if (MO.isDef()) {
365dd58ef01SDimitry Andric PRI.Defined = true;
366dd58ef01SDimitry Andric if (Covered)
367dd58ef01SDimitry Andric PRI.FullyDefined = true;
368522600a2SDimitry Andric if (!MO.isDead())
369522600a2SDimitry Andric AllDefsDead = false;
370522600a2SDimitry Andric }
371522600a2SDimitry Andric }
372522600a2SDimitry Andric
37301095a5dSDimitry Andric if (AllDefsDead) {
37401095a5dSDimitry Andric if (PRI.FullyDefined || PRI.Clobbered)
375dd58ef01SDimitry Andric PRI.DeadDef = true;
37601095a5dSDimitry Andric else if (PRI.Defined)
37701095a5dSDimitry Andric PRI.PartialDeadDef = true;
37801095a5dSDimitry Andric }
379522600a2SDimitry Andric
380522600a2SDimitry Andric return PRI;
381522600a2SDimitry Andric }
382