10b57cec5SDimitry Andric //===-- lib/CodeGen/MachineInstrBundle.cpp --------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBundle.h"
100b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h"
110b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
120b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
130b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
140b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
18480093f4SDimitry Andric #include "llvm/InitializePasses.h"
1981ad6265SDimitry Andric #include "llvm/Pass.h"
2081ad6265SDimitry Andric #include "llvm/PassRegistry.h"
210b57cec5SDimitry Andric #include <utility>
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric namespace {
250b57cec5SDimitry Andric class UnpackMachineBundles : public MachineFunctionPass {
260b57cec5SDimitry Andric public:
270b57cec5SDimitry Andric static char ID; // Pass identification
UnpackMachineBundles(std::function<bool (const MachineFunction &)> Ftor=nullptr)280b57cec5SDimitry Andric UnpackMachineBundles(
290b57cec5SDimitry Andric std::function<bool(const MachineFunction &)> Ftor = nullptr)
300b57cec5SDimitry Andric : MachineFunctionPass(ID), PredicateFtor(std::move(Ftor)) {
310b57cec5SDimitry Andric initializeUnpackMachineBundlesPass(*PassRegistry::getPassRegistry());
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric private:
370b57cec5SDimitry Andric std::function<bool(const MachineFunction &)> PredicateFtor;
380b57cec5SDimitry Andric };
390b57cec5SDimitry Andric } // end anonymous namespace
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric char UnpackMachineBundles::ID = 0;
420b57cec5SDimitry Andric char &llvm::UnpackMachineBundlesID = UnpackMachineBundles::ID;
430b57cec5SDimitry Andric INITIALIZE_PASS(UnpackMachineBundles, "unpack-mi-bundles",
440b57cec5SDimitry Andric "Unpack machine instruction bundles", false, false)
450b57cec5SDimitry Andric
runOnMachineFunction(MachineFunction & MF)460b57cec5SDimitry Andric bool UnpackMachineBundles::runOnMachineFunction(MachineFunction &MF) {
470b57cec5SDimitry Andric if (PredicateFtor && !PredicateFtor(MF))
480b57cec5SDimitry Andric return false;
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric bool Changed = false;
51fe6060f1SDimitry Andric for (MachineBasicBlock &MBB : MF) {
52fe6060f1SDimitry Andric for (MachineBasicBlock::instr_iterator MII = MBB.instr_begin(),
53fe6060f1SDimitry Andric MIE = MBB.instr_end(); MII != MIE; ) {
540b57cec5SDimitry Andric MachineInstr *MI = &*MII;
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric // Remove BUNDLE instruction and the InsideBundle flags from bundled
570b57cec5SDimitry Andric // instructions.
580b57cec5SDimitry Andric if (MI->isBundle()) {
590b57cec5SDimitry Andric while (++MII != MIE && MII->isBundledWithPred()) {
600b57cec5SDimitry Andric MII->unbundleFromPred();
6106c3fb27SDimitry Andric for (MachineOperand &MO : MII->operands()) {
620b57cec5SDimitry Andric if (MO.isReg() && MO.isInternalRead())
630b57cec5SDimitry Andric MO.setIsInternalRead(false);
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric MI->eraseFromParent();
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric Changed = true;
690b57cec5SDimitry Andric continue;
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric ++MII;
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric return Changed;
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric FunctionPass *
createUnpackMachineBundles(std::function<bool (const MachineFunction &)> Ftor)800b57cec5SDimitry Andric llvm::createUnpackMachineBundles(
810b57cec5SDimitry Andric std::function<bool(const MachineFunction &)> Ftor) {
820b57cec5SDimitry Andric return new UnpackMachineBundles(std::move(Ftor));
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric namespace {
860b57cec5SDimitry Andric class FinalizeMachineBundles : public MachineFunctionPass {
870b57cec5SDimitry Andric public:
880b57cec5SDimitry Andric static char ID; // Pass identification
FinalizeMachineBundles()890b57cec5SDimitry Andric FinalizeMachineBundles() : MachineFunctionPass(ID) {
900b57cec5SDimitry Andric initializeFinalizeMachineBundlesPass(*PassRegistry::getPassRegistry());
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
940b57cec5SDimitry Andric };
950b57cec5SDimitry Andric } // end anonymous namespace
960b57cec5SDimitry Andric
970b57cec5SDimitry Andric char FinalizeMachineBundles::ID = 0;
980b57cec5SDimitry Andric char &llvm::FinalizeMachineBundlesID = FinalizeMachineBundles::ID;
990b57cec5SDimitry Andric INITIALIZE_PASS(FinalizeMachineBundles, "finalize-mi-bundles",
1000b57cec5SDimitry Andric "Finalize machine instruction bundles", false, false)
1010b57cec5SDimitry Andric
runOnMachineFunction(MachineFunction & MF)1020b57cec5SDimitry Andric bool FinalizeMachineBundles::runOnMachineFunction(MachineFunction &MF) {
1030b57cec5SDimitry Andric return llvm::finalizeBundles(MF);
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andric /// Return the first found DebugLoc that has a DILocation, given a range of
1070b57cec5SDimitry Andric /// instructions. The search range is from FirstMI to LastMI (exclusive). If no
1080b57cec5SDimitry Andric /// DILocation is found, then an empty location is returned.
getDebugLoc(MachineBasicBlock::instr_iterator FirstMI,MachineBasicBlock::instr_iterator LastMI)1090b57cec5SDimitry Andric static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI,
1100b57cec5SDimitry Andric MachineBasicBlock::instr_iterator LastMI) {
1110b57cec5SDimitry Andric for (auto MII = FirstMI; MII != LastMI; ++MII)
11281ad6265SDimitry Andric if (MII->getDebugLoc())
1130b57cec5SDimitry Andric return MII->getDebugLoc();
1140b57cec5SDimitry Andric return DebugLoc();
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric /// finalizeBundle - Finalize a machine instruction bundle which includes
1180b57cec5SDimitry Andric /// a sequence of instructions starting from FirstMI to LastMI (exclusive).
1190b57cec5SDimitry Andric /// This routine adds a BUNDLE instruction to represent the bundle, it adds
1200b57cec5SDimitry Andric /// IsInternalRead markers to MachineOperands which are defined inside the
1210b57cec5SDimitry Andric /// bundle, and it copies externally visible defs and uses to the BUNDLE
1220b57cec5SDimitry Andric /// instruction.
finalizeBundle(MachineBasicBlock & MBB,MachineBasicBlock::instr_iterator FirstMI,MachineBasicBlock::instr_iterator LastMI)1230b57cec5SDimitry Andric void llvm::finalizeBundle(MachineBasicBlock &MBB,
1240b57cec5SDimitry Andric MachineBasicBlock::instr_iterator FirstMI,
1250b57cec5SDimitry Andric MachineBasicBlock::instr_iterator LastMI) {
1260b57cec5SDimitry Andric assert(FirstMI != LastMI && "Empty bundle?");
1270b57cec5SDimitry Andric MIBundleBuilder Bundle(MBB, FirstMI, LastMI);
1280b57cec5SDimitry Andric
1290b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent();
1300b57cec5SDimitry Andric const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
1310b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
1320b57cec5SDimitry Andric
1330b57cec5SDimitry Andric MachineInstrBuilder MIB =
1340b57cec5SDimitry Andric BuildMI(MF, getDebugLoc(FirstMI, LastMI), TII->get(TargetOpcode::BUNDLE));
1350b57cec5SDimitry Andric Bundle.prepend(MIB);
1360b57cec5SDimitry Andric
1375ffd83dbSDimitry Andric SmallVector<Register, 32> LocalDefs;
1385ffd83dbSDimitry Andric SmallSet<Register, 32> LocalDefSet;
1395ffd83dbSDimitry Andric SmallSet<Register, 8> DeadDefSet;
1405ffd83dbSDimitry Andric SmallSet<Register, 16> KilledDefSet;
1415ffd83dbSDimitry Andric SmallVector<Register, 8> ExternUses;
1425ffd83dbSDimitry Andric SmallSet<Register, 8> ExternUseSet;
1435ffd83dbSDimitry Andric SmallSet<Register, 8> KilledUseSet;
1445ffd83dbSDimitry Andric SmallSet<Register, 8> UndefUseSet;
1450b57cec5SDimitry Andric SmallVector<MachineOperand*, 4> Defs;
1460b57cec5SDimitry Andric for (auto MII = FirstMI; MII != LastMI; ++MII) {
14704eeddc0SDimitry Andric // Debug instructions have no effects to track.
14804eeddc0SDimitry Andric if (MII->isDebugInstr())
14904eeddc0SDimitry Andric continue;
15004eeddc0SDimitry Andric
15106c3fb27SDimitry Andric for (MachineOperand &MO : MII->operands()) {
1520b57cec5SDimitry Andric if (!MO.isReg())
1530b57cec5SDimitry Andric continue;
1540b57cec5SDimitry Andric if (MO.isDef()) {
1550b57cec5SDimitry Andric Defs.push_back(&MO);
1560b57cec5SDimitry Andric continue;
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric
1598bcb0991SDimitry Andric Register Reg = MO.getReg();
1600b57cec5SDimitry Andric if (!Reg)
1610b57cec5SDimitry Andric continue;
1628bcb0991SDimitry Andric
1630b57cec5SDimitry Andric if (LocalDefSet.count(Reg)) {
1640b57cec5SDimitry Andric MO.setIsInternalRead();
1650b57cec5SDimitry Andric if (MO.isKill())
1660b57cec5SDimitry Andric // Internal def is now killed.
1670b57cec5SDimitry Andric KilledDefSet.insert(Reg);
1680b57cec5SDimitry Andric } else {
1690b57cec5SDimitry Andric if (ExternUseSet.insert(Reg).second) {
1700b57cec5SDimitry Andric ExternUses.push_back(Reg);
1710b57cec5SDimitry Andric if (MO.isUndef())
1720b57cec5SDimitry Andric UndefUseSet.insert(Reg);
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric if (MO.isKill())
1750b57cec5SDimitry Andric // External def is now killed.
1760b57cec5SDimitry Andric KilledUseSet.insert(Reg);
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric
180*0fca6ea1SDimitry Andric for (MachineOperand *MO : Defs) {
181*0fca6ea1SDimitry Andric Register Reg = MO->getReg();
1820b57cec5SDimitry Andric if (!Reg)
1830b57cec5SDimitry Andric continue;
1840b57cec5SDimitry Andric
1850b57cec5SDimitry Andric if (LocalDefSet.insert(Reg).second) {
1860b57cec5SDimitry Andric LocalDefs.push_back(Reg);
187*0fca6ea1SDimitry Andric if (MO->isDead()) {
1880b57cec5SDimitry Andric DeadDefSet.insert(Reg);
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric } else {
1910b57cec5SDimitry Andric // Re-defined inside the bundle, it's no longer killed.
1920b57cec5SDimitry Andric KilledDefSet.erase(Reg);
193*0fca6ea1SDimitry Andric if (!MO->isDead())
1940b57cec5SDimitry Andric // Previously defined but dead.
1950b57cec5SDimitry Andric DeadDefSet.erase(Reg);
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric
198*0fca6ea1SDimitry Andric if (!MO->isDead() && Reg.isPhysical()) {
19906c3fb27SDimitry Andric for (MCPhysReg SubReg : TRI->subregs(Reg)) {
2000b57cec5SDimitry Andric if (LocalDefSet.insert(SubReg).second)
2010b57cec5SDimitry Andric LocalDefs.push_back(SubReg);
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric
2060b57cec5SDimitry Andric Defs.clear();
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric
2095ffd83dbSDimitry Andric SmallSet<Register, 32> Added;
210cb14a3feSDimitry Andric for (Register Reg : LocalDefs) {
2110b57cec5SDimitry Andric if (Added.insert(Reg).second) {
2120b57cec5SDimitry Andric // If it's not live beyond end of the bundle, mark it dead.
2130b57cec5SDimitry Andric bool isDead = DeadDefSet.count(Reg) || KilledDefSet.count(Reg);
2140b57cec5SDimitry Andric MIB.addReg(Reg, getDefRegState(true) | getDeadRegState(isDead) |
2150b57cec5SDimitry Andric getImplRegState(true));
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric
219cb14a3feSDimitry Andric for (Register Reg : ExternUses) {
2200b57cec5SDimitry Andric bool isKill = KilledUseSet.count(Reg);
2210b57cec5SDimitry Andric bool isUndef = UndefUseSet.count(Reg);
2220b57cec5SDimitry Andric MIB.addReg(Reg, getKillRegState(isKill) | getUndefRegState(isUndef) |
2230b57cec5SDimitry Andric getImplRegState(true));
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric
2260b57cec5SDimitry Andric // Set FrameSetup/FrameDestroy for the bundle. If any of the instructions got
2270b57cec5SDimitry Andric // the property, then also set it on the bundle.
2280b57cec5SDimitry Andric for (auto MII = FirstMI; MII != LastMI; ++MII) {
2290b57cec5SDimitry Andric if (MII->getFlag(MachineInstr::FrameSetup))
2300b57cec5SDimitry Andric MIB.setMIFlag(MachineInstr::FrameSetup);
2310b57cec5SDimitry Andric if (MII->getFlag(MachineInstr::FrameDestroy))
2320b57cec5SDimitry Andric MIB.setMIFlag(MachineInstr::FrameDestroy);
2330b57cec5SDimitry Andric }
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric /// finalizeBundle - Same functionality as the previous finalizeBundle except
2370b57cec5SDimitry Andric /// the last instruction in the bundle is not provided as an input. This is
2380b57cec5SDimitry Andric /// used in cases where bundles are pre-determined by marking instructions
2390b57cec5SDimitry Andric /// with 'InsideBundle' marker. It returns the MBB instruction iterator that
2400b57cec5SDimitry Andric /// points to the end of the bundle.
2410b57cec5SDimitry Andric MachineBasicBlock::instr_iterator
finalizeBundle(MachineBasicBlock & MBB,MachineBasicBlock::instr_iterator FirstMI)2420b57cec5SDimitry Andric llvm::finalizeBundle(MachineBasicBlock &MBB,
2430b57cec5SDimitry Andric MachineBasicBlock::instr_iterator FirstMI) {
2440b57cec5SDimitry Andric MachineBasicBlock::instr_iterator E = MBB.instr_end();
2450b57cec5SDimitry Andric MachineBasicBlock::instr_iterator LastMI = std::next(FirstMI);
2460b57cec5SDimitry Andric while (LastMI != E && LastMI->isInsideBundle())
2470b57cec5SDimitry Andric ++LastMI;
2480b57cec5SDimitry Andric finalizeBundle(MBB, FirstMI, LastMI);
2490b57cec5SDimitry Andric return LastMI;
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric /// finalizeBundles - Finalize instruction bundles in the specified
2530b57cec5SDimitry Andric /// MachineFunction. Return true if any bundles are finalized.
finalizeBundles(MachineFunction & MF)2540b57cec5SDimitry Andric bool llvm::finalizeBundles(MachineFunction &MF) {
2550b57cec5SDimitry Andric bool Changed = false;
256fe6060f1SDimitry Andric for (MachineBasicBlock &MBB : MF) {
2570b57cec5SDimitry Andric MachineBasicBlock::instr_iterator MII = MBB.instr_begin();
2580b57cec5SDimitry Andric MachineBasicBlock::instr_iterator MIE = MBB.instr_end();
2590b57cec5SDimitry Andric if (MII == MIE)
2600b57cec5SDimitry Andric continue;
2610b57cec5SDimitry Andric assert(!MII->isInsideBundle() &&
2620b57cec5SDimitry Andric "First instr cannot be inside bundle before finalization!");
2630b57cec5SDimitry Andric
2640b57cec5SDimitry Andric for (++MII; MII != MIE; ) {
2650b57cec5SDimitry Andric if (!MII->isInsideBundle())
2660b57cec5SDimitry Andric ++MII;
2670b57cec5SDimitry Andric else {
2680b57cec5SDimitry Andric MII = finalizeBundle(MBB, std::prev(MII));
2690b57cec5SDimitry Andric Changed = true;
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric }
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric
2740b57cec5SDimitry Andric return Changed;
2750b57cec5SDimitry Andric }
2760b57cec5SDimitry Andric
AnalyzeVirtRegInBundle(MachineInstr & MI,Register Reg,SmallVectorImpl<std::pair<MachineInstr *,unsigned>> * Ops)277480093f4SDimitry Andric VirtRegInfo llvm::AnalyzeVirtRegInBundle(
2785ffd83dbSDimitry Andric MachineInstr &MI, Register Reg,
2790b57cec5SDimitry Andric SmallVectorImpl<std::pair<MachineInstr *, unsigned>> *Ops) {
2800b57cec5SDimitry Andric VirtRegInfo RI = {false, false, false};
281480093f4SDimitry Andric for (MIBundleOperands O(MI); O.isValid(); ++O) {
282480093f4SDimitry Andric MachineOperand &MO = *O;
2830b57cec5SDimitry Andric if (!MO.isReg() || MO.getReg() != Reg)
2840b57cec5SDimitry Andric continue;
2850b57cec5SDimitry Andric
2860b57cec5SDimitry Andric // Remember each (MI, OpNo) that refers to Reg.
2870b57cec5SDimitry Andric if (Ops)
288480093f4SDimitry Andric Ops->push_back(std::make_pair(MO.getParent(), O.getOperandNo()));
2890b57cec5SDimitry Andric
2900b57cec5SDimitry Andric // Both defs and uses can read virtual registers.
2910b57cec5SDimitry Andric if (MO.readsReg()) {
2920b57cec5SDimitry Andric RI.Reads = true;
2930b57cec5SDimitry Andric if (MO.isDef())
2940b57cec5SDimitry Andric RI.Tied = true;
2950b57cec5SDimitry Andric }
2960b57cec5SDimitry Andric
2970b57cec5SDimitry Andric // Only defs can write.
2980b57cec5SDimitry Andric if (MO.isDef())
2990b57cec5SDimitry Andric RI.Writes = true;
300480093f4SDimitry Andric else if (!RI.Tied &&
301480093f4SDimitry Andric MO.getParent()->isRegTiedToDefOperand(O.getOperandNo()))
3020b57cec5SDimitry Andric RI.Tied = true;
3030b57cec5SDimitry Andric }
3040b57cec5SDimitry Andric return RI;
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric
30706c3fb27SDimitry Andric std::pair<LaneBitmask, LaneBitmask>
AnalyzeVirtRegLanesInBundle(const MachineInstr & MI,Register Reg,const MachineRegisterInfo & MRI,const TargetRegisterInfo & TRI)30806c3fb27SDimitry Andric llvm::AnalyzeVirtRegLanesInBundle(const MachineInstr &MI, Register Reg,
30906c3fb27SDimitry Andric const MachineRegisterInfo &MRI,
31006c3fb27SDimitry Andric const TargetRegisterInfo &TRI) {
31106c3fb27SDimitry Andric
31206c3fb27SDimitry Andric LaneBitmask UseMask, DefMask;
31306c3fb27SDimitry Andric
314*0fca6ea1SDimitry Andric for (const MachineOperand &MO : const_mi_bundle_ops(MI)) {
31506c3fb27SDimitry Andric if (!MO.isReg() || MO.getReg() != Reg)
31606c3fb27SDimitry Andric continue;
31706c3fb27SDimitry Andric
31806c3fb27SDimitry Andric unsigned SubReg = MO.getSubReg();
31906c3fb27SDimitry Andric if (SubReg == 0 && MO.isUse() && !MO.isUndef())
32006c3fb27SDimitry Andric UseMask |= MRI.getMaxLaneMaskForVReg(Reg);
32106c3fb27SDimitry Andric
32206c3fb27SDimitry Andric LaneBitmask SubRegMask = TRI.getSubRegIndexLaneMask(SubReg);
32306c3fb27SDimitry Andric if (MO.isDef()) {
32406c3fb27SDimitry Andric if (!MO.isUndef())
32506c3fb27SDimitry Andric UseMask |= ~SubRegMask;
32606c3fb27SDimitry Andric DefMask |= SubRegMask;
32706c3fb27SDimitry Andric } else if (!MO.isUndef())
32806c3fb27SDimitry Andric UseMask |= SubRegMask;
32906c3fb27SDimitry Andric }
33006c3fb27SDimitry Andric
33106c3fb27SDimitry Andric return {UseMask, DefMask};
33206c3fb27SDimitry Andric }
33306c3fb27SDimitry Andric
AnalyzePhysRegInBundle(const MachineInstr & MI,Register Reg,const TargetRegisterInfo * TRI)3345ffd83dbSDimitry Andric PhysRegInfo llvm::AnalyzePhysRegInBundle(const MachineInstr &MI, Register Reg,
3350b57cec5SDimitry Andric const TargetRegisterInfo *TRI) {
3360b57cec5SDimitry Andric bool AllDefsDead = true;
3370b57cec5SDimitry Andric PhysRegInfo PRI = {false, false, false, false, false, false, false, false};
3380b57cec5SDimitry Andric
3395ffd83dbSDimitry Andric assert(Reg.isPhysical() && "analyzePhysReg not given a physical register!");
340*0fca6ea1SDimitry Andric for (const MachineOperand &MO : const_mi_bundle_ops(MI)) {
3410b57cec5SDimitry Andric if (MO.isRegMask() && MO.clobbersPhysReg(Reg)) {
3420b57cec5SDimitry Andric PRI.Clobbered = true;
3430b57cec5SDimitry Andric continue;
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric
3460b57cec5SDimitry Andric if (!MO.isReg())
3470b57cec5SDimitry Andric continue;
3480b57cec5SDimitry Andric
3498bcb0991SDimitry Andric Register MOReg = MO.getReg();
350bdd1243dSDimitry Andric if (!MOReg || !MOReg.isPhysical())
3510b57cec5SDimitry Andric continue;
3520b57cec5SDimitry Andric
3530b57cec5SDimitry Andric if (!TRI->regsOverlap(MOReg, Reg))
3540b57cec5SDimitry Andric continue;
3550b57cec5SDimitry Andric
3560b57cec5SDimitry Andric bool Covered = TRI->isSuperRegisterEq(Reg, MOReg);
3570b57cec5SDimitry Andric if (MO.readsReg()) {
3580b57cec5SDimitry Andric PRI.Read = true;
3590b57cec5SDimitry Andric if (Covered) {
3600b57cec5SDimitry Andric PRI.FullyRead = true;
3610b57cec5SDimitry Andric if (MO.isKill())
3620b57cec5SDimitry Andric PRI.Killed = true;
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric } else if (MO.isDef()) {
3650b57cec5SDimitry Andric PRI.Defined = true;
3660b57cec5SDimitry Andric if (Covered)
3670b57cec5SDimitry Andric PRI.FullyDefined = true;
3680b57cec5SDimitry Andric if (!MO.isDead())
3690b57cec5SDimitry Andric AllDefsDead = false;
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric }
3720b57cec5SDimitry Andric
3730b57cec5SDimitry Andric if (AllDefsDead) {
3740b57cec5SDimitry Andric if (PRI.FullyDefined || PRI.Clobbered)
3750b57cec5SDimitry Andric PRI.DeadDef = true;
3760b57cec5SDimitry Andric else if (PRI.Defined)
3770b57cec5SDimitry Andric PRI.PartialDeadDef = true;
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric
3800b57cec5SDimitry Andric return PRI;
3810b57cec5SDimitry Andric }
382