xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/MachineInstrBundle.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===-- lib/CodeGen/MachineInstrBundle.cpp --------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBundle.h"
10*0b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h"
11*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
12*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
13*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
14*0b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
15*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
16*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
17*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
18*0b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
19*0b57cec5SDimitry Andric #include <utility>
20*0b57cec5SDimitry Andric using namespace llvm;
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric namespace {
23*0b57cec5SDimitry Andric   class UnpackMachineBundles : public MachineFunctionPass {
24*0b57cec5SDimitry Andric   public:
25*0b57cec5SDimitry Andric     static char ID; // Pass identification
26*0b57cec5SDimitry Andric     UnpackMachineBundles(
27*0b57cec5SDimitry Andric         std::function<bool(const MachineFunction &)> Ftor = nullptr)
28*0b57cec5SDimitry Andric         : MachineFunctionPass(ID), PredicateFtor(std::move(Ftor)) {
29*0b57cec5SDimitry Andric       initializeUnpackMachineBundlesPass(*PassRegistry::getPassRegistry());
30*0b57cec5SDimitry Andric     }
31*0b57cec5SDimitry Andric 
32*0b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override;
33*0b57cec5SDimitry Andric 
34*0b57cec5SDimitry Andric   private:
35*0b57cec5SDimitry Andric     std::function<bool(const MachineFunction &)> PredicateFtor;
36*0b57cec5SDimitry Andric   };
37*0b57cec5SDimitry Andric } // end anonymous namespace
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric char UnpackMachineBundles::ID = 0;
40*0b57cec5SDimitry Andric char &llvm::UnpackMachineBundlesID = UnpackMachineBundles::ID;
41*0b57cec5SDimitry Andric INITIALIZE_PASS(UnpackMachineBundles, "unpack-mi-bundles",
42*0b57cec5SDimitry Andric                 "Unpack machine instruction bundles", false, false)
43*0b57cec5SDimitry Andric 
44*0b57cec5SDimitry Andric bool UnpackMachineBundles::runOnMachineFunction(MachineFunction &MF) {
45*0b57cec5SDimitry Andric   if (PredicateFtor && !PredicateFtor(MF))
46*0b57cec5SDimitry Andric     return false;
47*0b57cec5SDimitry Andric 
48*0b57cec5SDimitry Andric   bool Changed = false;
49*0b57cec5SDimitry Andric   for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
50*0b57cec5SDimitry Andric     MachineBasicBlock *MBB = &*I;
51*0b57cec5SDimitry Andric 
52*0b57cec5SDimitry Andric     for (MachineBasicBlock::instr_iterator MII = MBB->instr_begin(),
53*0b57cec5SDimitry Andric            MIE = MBB->instr_end(); MII != MIE; ) {
54*0b57cec5SDimitry Andric       MachineInstr *MI = &*MII;
55*0b57cec5SDimitry Andric 
56*0b57cec5SDimitry Andric       // Remove BUNDLE instruction and the InsideBundle flags from bundled
57*0b57cec5SDimitry Andric       // instructions.
58*0b57cec5SDimitry Andric       if (MI->isBundle()) {
59*0b57cec5SDimitry Andric         while (++MII != MIE && MII->isBundledWithPred()) {
60*0b57cec5SDimitry Andric           MII->unbundleFromPred();
61*0b57cec5SDimitry Andric           for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) {
62*0b57cec5SDimitry Andric             MachineOperand &MO = MII->getOperand(i);
63*0b57cec5SDimitry Andric             if (MO.isReg() && MO.isInternalRead())
64*0b57cec5SDimitry Andric               MO.setIsInternalRead(false);
65*0b57cec5SDimitry Andric           }
66*0b57cec5SDimitry Andric         }
67*0b57cec5SDimitry Andric         MI->eraseFromParent();
68*0b57cec5SDimitry Andric 
69*0b57cec5SDimitry Andric         Changed = true;
70*0b57cec5SDimitry Andric         continue;
71*0b57cec5SDimitry Andric       }
72*0b57cec5SDimitry Andric 
73*0b57cec5SDimitry Andric       ++MII;
74*0b57cec5SDimitry Andric     }
75*0b57cec5SDimitry Andric   }
76*0b57cec5SDimitry Andric 
77*0b57cec5SDimitry Andric   return Changed;
78*0b57cec5SDimitry Andric }
79*0b57cec5SDimitry Andric 
80*0b57cec5SDimitry Andric FunctionPass *
81*0b57cec5SDimitry Andric llvm::createUnpackMachineBundles(
82*0b57cec5SDimitry Andric     std::function<bool(const MachineFunction &)> Ftor) {
83*0b57cec5SDimitry Andric   return new UnpackMachineBundles(std::move(Ftor));
84*0b57cec5SDimitry Andric }
85*0b57cec5SDimitry Andric 
86*0b57cec5SDimitry Andric namespace {
87*0b57cec5SDimitry Andric   class FinalizeMachineBundles : public MachineFunctionPass {
88*0b57cec5SDimitry Andric   public:
89*0b57cec5SDimitry Andric     static char ID; // Pass identification
90*0b57cec5SDimitry Andric     FinalizeMachineBundles() : MachineFunctionPass(ID) {
91*0b57cec5SDimitry Andric       initializeFinalizeMachineBundlesPass(*PassRegistry::getPassRegistry());
92*0b57cec5SDimitry Andric     }
93*0b57cec5SDimitry Andric 
94*0b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override;
95*0b57cec5SDimitry Andric   };
96*0b57cec5SDimitry Andric } // end anonymous namespace
97*0b57cec5SDimitry Andric 
98*0b57cec5SDimitry Andric char FinalizeMachineBundles::ID = 0;
99*0b57cec5SDimitry Andric char &llvm::FinalizeMachineBundlesID = FinalizeMachineBundles::ID;
100*0b57cec5SDimitry Andric INITIALIZE_PASS(FinalizeMachineBundles, "finalize-mi-bundles",
101*0b57cec5SDimitry Andric                 "Finalize machine instruction bundles", false, false)
102*0b57cec5SDimitry Andric 
103*0b57cec5SDimitry Andric bool FinalizeMachineBundles::runOnMachineFunction(MachineFunction &MF) {
104*0b57cec5SDimitry Andric   return llvm::finalizeBundles(MF);
105*0b57cec5SDimitry Andric }
106*0b57cec5SDimitry Andric 
107*0b57cec5SDimitry Andric /// Return the first found DebugLoc that has a DILocation, given a range of
108*0b57cec5SDimitry Andric /// instructions. The search range is from FirstMI to LastMI (exclusive). If no
109*0b57cec5SDimitry Andric /// DILocation is found, then an empty location is returned.
110*0b57cec5SDimitry Andric static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI,
111*0b57cec5SDimitry Andric                             MachineBasicBlock::instr_iterator LastMI) {
112*0b57cec5SDimitry Andric   for (auto MII = FirstMI; MII != LastMI; ++MII)
113*0b57cec5SDimitry Andric     if (MII->getDebugLoc().get())
114*0b57cec5SDimitry Andric       return MII->getDebugLoc();
115*0b57cec5SDimitry Andric   return DebugLoc();
116*0b57cec5SDimitry Andric }
117*0b57cec5SDimitry Andric 
118*0b57cec5SDimitry Andric /// finalizeBundle - Finalize a machine instruction bundle which includes
119*0b57cec5SDimitry Andric /// a sequence of instructions starting from FirstMI to LastMI (exclusive).
120*0b57cec5SDimitry Andric /// This routine adds a BUNDLE instruction to represent the bundle, it adds
121*0b57cec5SDimitry Andric /// IsInternalRead markers to MachineOperands which are defined inside the
122*0b57cec5SDimitry Andric /// bundle, and it copies externally visible defs and uses to the BUNDLE
123*0b57cec5SDimitry Andric /// instruction.
124*0b57cec5SDimitry Andric void llvm::finalizeBundle(MachineBasicBlock &MBB,
125*0b57cec5SDimitry Andric                           MachineBasicBlock::instr_iterator FirstMI,
126*0b57cec5SDimitry Andric                           MachineBasicBlock::instr_iterator LastMI) {
127*0b57cec5SDimitry Andric   assert(FirstMI != LastMI && "Empty bundle?");
128*0b57cec5SDimitry Andric   MIBundleBuilder Bundle(MBB, FirstMI, LastMI);
129*0b57cec5SDimitry Andric 
130*0b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
131*0b57cec5SDimitry Andric   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
132*0b57cec5SDimitry Andric   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
133*0b57cec5SDimitry Andric 
134*0b57cec5SDimitry Andric   MachineInstrBuilder MIB =
135*0b57cec5SDimitry Andric       BuildMI(MF, getDebugLoc(FirstMI, LastMI), TII->get(TargetOpcode::BUNDLE));
136*0b57cec5SDimitry Andric   Bundle.prepend(MIB);
137*0b57cec5SDimitry Andric 
138*0b57cec5SDimitry Andric   SmallVector<unsigned, 32> LocalDefs;
139*0b57cec5SDimitry Andric   SmallSet<unsigned, 32> LocalDefSet;
140*0b57cec5SDimitry Andric   SmallSet<unsigned, 8> DeadDefSet;
141*0b57cec5SDimitry Andric   SmallSet<unsigned, 16> KilledDefSet;
142*0b57cec5SDimitry Andric   SmallVector<unsigned, 8> ExternUses;
143*0b57cec5SDimitry Andric   SmallSet<unsigned, 8> ExternUseSet;
144*0b57cec5SDimitry Andric   SmallSet<unsigned, 8> KilledUseSet;
145*0b57cec5SDimitry Andric   SmallSet<unsigned, 8> UndefUseSet;
146*0b57cec5SDimitry Andric   SmallVector<MachineOperand*, 4> Defs;
147*0b57cec5SDimitry Andric   for (auto MII = FirstMI; MII != LastMI; ++MII) {
148*0b57cec5SDimitry Andric     for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) {
149*0b57cec5SDimitry Andric       MachineOperand &MO = MII->getOperand(i);
150*0b57cec5SDimitry Andric       if (!MO.isReg())
151*0b57cec5SDimitry Andric         continue;
152*0b57cec5SDimitry Andric       if (MO.isDef()) {
153*0b57cec5SDimitry Andric         Defs.push_back(&MO);
154*0b57cec5SDimitry Andric         continue;
155*0b57cec5SDimitry Andric       }
156*0b57cec5SDimitry Andric 
157*0b57cec5SDimitry Andric       unsigned Reg = MO.getReg();
158*0b57cec5SDimitry Andric       if (!Reg)
159*0b57cec5SDimitry Andric         continue;
160*0b57cec5SDimitry Andric       assert(TargetRegisterInfo::isPhysicalRegister(Reg));
161*0b57cec5SDimitry Andric       if (LocalDefSet.count(Reg)) {
162*0b57cec5SDimitry Andric         MO.setIsInternalRead();
163*0b57cec5SDimitry Andric         if (MO.isKill())
164*0b57cec5SDimitry Andric           // Internal def is now killed.
165*0b57cec5SDimitry Andric           KilledDefSet.insert(Reg);
166*0b57cec5SDimitry Andric       } else {
167*0b57cec5SDimitry Andric         if (ExternUseSet.insert(Reg).second) {
168*0b57cec5SDimitry Andric           ExternUses.push_back(Reg);
169*0b57cec5SDimitry Andric           if (MO.isUndef())
170*0b57cec5SDimitry Andric             UndefUseSet.insert(Reg);
171*0b57cec5SDimitry Andric         }
172*0b57cec5SDimitry Andric         if (MO.isKill())
173*0b57cec5SDimitry Andric           // External def is now killed.
174*0b57cec5SDimitry Andric           KilledUseSet.insert(Reg);
175*0b57cec5SDimitry Andric       }
176*0b57cec5SDimitry Andric     }
177*0b57cec5SDimitry Andric 
178*0b57cec5SDimitry Andric     for (unsigned i = 0, e = Defs.size(); i != e; ++i) {
179*0b57cec5SDimitry Andric       MachineOperand &MO = *Defs[i];
180*0b57cec5SDimitry Andric       unsigned Reg = MO.getReg();
181*0b57cec5SDimitry Andric       if (!Reg)
182*0b57cec5SDimitry Andric         continue;
183*0b57cec5SDimitry Andric 
184*0b57cec5SDimitry Andric       if (LocalDefSet.insert(Reg).second) {
185*0b57cec5SDimitry Andric         LocalDefs.push_back(Reg);
186*0b57cec5SDimitry Andric         if (MO.isDead()) {
187*0b57cec5SDimitry Andric           DeadDefSet.insert(Reg);
188*0b57cec5SDimitry Andric         }
189*0b57cec5SDimitry Andric       } else {
190*0b57cec5SDimitry Andric         // Re-defined inside the bundle, it's no longer killed.
191*0b57cec5SDimitry Andric         KilledDefSet.erase(Reg);
192*0b57cec5SDimitry Andric         if (!MO.isDead())
193*0b57cec5SDimitry Andric           // Previously defined but dead.
194*0b57cec5SDimitry Andric           DeadDefSet.erase(Reg);
195*0b57cec5SDimitry Andric       }
196*0b57cec5SDimitry Andric 
197*0b57cec5SDimitry Andric       if (!MO.isDead()) {
198*0b57cec5SDimitry Andric         for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs) {
199*0b57cec5SDimitry Andric           unsigned SubReg = *SubRegs;
200*0b57cec5SDimitry Andric           if (LocalDefSet.insert(SubReg).second)
201*0b57cec5SDimitry Andric             LocalDefs.push_back(SubReg);
202*0b57cec5SDimitry Andric         }
203*0b57cec5SDimitry Andric       }
204*0b57cec5SDimitry Andric     }
205*0b57cec5SDimitry Andric 
206*0b57cec5SDimitry Andric     Defs.clear();
207*0b57cec5SDimitry Andric   }
208*0b57cec5SDimitry Andric 
209*0b57cec5SDimitry Andric   SmallSet<unsigned, 32> Added;
210*0b57cec5SDimitry Andric   for (unsigned i = 0, e = LocalDefs.size(); i != e; ++i) {
211*0b57cec5SDimitry Andric     unsigned Reg = LocalDefs[i];
212*0b57cec5SDimitry Andric     if (Added.insert(Reg).second) {
213*0b57cec5SDimitry Andric       // If it's not live beyond end of the bundle, mark it dead.
214*0b57cec5SDimitry Andric       bool isDead = DeadDefSet.count(Reg) || KilledDefSet.count(Reg);
215*0b57cec5SDimitry Andric       MIB.addReg(Reg, getDefRegState(true) | getDeadRegState(isDead) |
216*0b57cec5SDimitry Andric                  getImplRegState(true));
217*0b57cec5SDimitry Andric     }
218*0b57cec5SDimitry Andric   }
219*0b57cec5SDimitry Andric 
220*0b57cec5SDimitry Andric   for (unsigned i = 0, e = ExternUses.size(); i != e; ++i) {
221*0b57cec5SDimitry Andric     unsigned Reg = ExternUses[i];
222*0b57cec5SDimitry Andric     bool isKill = KilledUseSet.count(Reg);
223*0b57cec5SDimitry Andric     bool isUndef = UndefUseSet.count(Reg);
224*0b57cec5SDimitry Andric     MIB.addReg(Reg, getKillRegState(isKill) | getUndefRegState(isUndef) |
225*0b57cec5SDimitry Andric                getImplRegState(true));
226*0b57cec5SDimitry Andric   }
227*0b57cec5SDimitry Andric 
228*0b57cec5SDimitry Andric   // Set FrameSetup/FrameDestroy for the bundle. If any of the instructions got
229*0b57cec5SDimitry Andric   // the property, then also set it on the bundle.
230*0b57cec5SDimitry Andric   for (auto MII = FirstMI; MII != LastMI; ++MII) {
231*0b57cec5SDimitry Andric     if (MII->getFlag(MachineInstr::FrameSetup))
232*0b57cec5SDimitry Andric       MIB.setMIFlag(MachineInstr::FrameSetup);
233*0b57cec5SDimitry Andric     if (MII->getFlag(MachineInstr::FrameDestroy))
234*0b57cec5SDimitry Andric       MIB.setMIFlag(MachineInstr::FrameDestroy);
235*0b57cec5SDimitry Andric   }
236*0b57cec5SDimitry Andric }
237*0b57cec5SDimitry Andric 
238*0b57cec5SDimitry Andric /// finalizeBundle - Same functionality as the previous finalizeBundle except
239*0b57cec5SDimitry Andric /// the last instruction in the bundle is not provided as an input. This is
240*0b57cec5SDimitry Andric /// used in cases where bundles are pre-determined by marking instructions
241*0b57cec5SDimitry Andric /// with 'InsideBundle' marker. It returns the MBB instruction iterator that
242*0b57cec5SDimitry Andric /// points to the end of the bundle.
243*0b57cec5SDimitry Andric MachineBasicBlock::instr_iterator
244*0b57cec5SDimitry Andric llvm::finalizeBundle(MachineBasicBlock &MBB,
245*0b57cec5SDimitry Andric                      MachineBasicBlock::instr_iterator FirstMI) {
246*0b57cec5SDimitry Andric   MachineBasicBlock::instr_iterator E = MBB.instr_end();
247*0b57cec5SDimitry Andric   MachineBasicBlock::instr_iterator LastMI = std::next(FirstMI);
248*0b57cec5SDimitry Andric   while (LastMI != E && LastMI->isInsideBundle())
249*0b57cec5SDimitry Andric     ++LastMI;
250*0b57cec5SDimitry Andric   finalizeBundle(MBB, FirstMI, LastMI);
251*0b57cec5SDimitry Andric   return LastMI;
252*0b57cec5SDimitry Andric }
253*0b57cec5SDimitry Andric 
254*0b57cec5SDimitry Andric /// finalizeBundles - Finalize instruction bundles in the specified
255*0b57cec5SDimitry Andric /// MachineFunction. Return true if any bundles are finalized.
256*0b57cec5SDimitry Andric bool llvm::finalizeBundles(MachineFunction &MF) {
257*0b57cec5SDimitry Andric   bool Changed = false;
258*0b57cec5SDimitry Andric   for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
259*0b57cec5SDimitry Andric     MachineBasicBlock &MBB = *I;
260*0b57cec5SDimitry Andric     MachineBasicBlock::instr_iterator MII = MBB.instr_begin();
261*0b57cec5SDimitry Andric     MachineBasicBlock::instr_iterator MIE = MBB.instr_end();
262*0b57cec5SDimitry Andric     if (MII == MIE)
263*0b57cec5SDimitry Andric       continue;
264*0b57cec5SDimitry Andric     assert(!MII->isInsideBundle() &&
265*0b57cec5SDimitry Andric            "First instr cannot be inside bundle before finalization!");
266*0b57cec5SDimitry Andric 
267*0b57cec5SDimitry Andric     for (++MII; MII != MIE; ) {
268*0b57cec5SDimitry Andric       if (!MII->isInsideBundle())
269*0b57cec5SDimitry Andric         ++MII;
270*0b57cec5SDimitry Andric       else {
271*0b57cec5SDimitry Andric         MII = finalizeBundle(MBB, std::prev(MII));
272*0b57cec5SDimitry Andric         Changed = true;
273*0b57cec5SDimitry Andric       }
274*0b57cec5SDimitry Andric     }
275*0b57cec5SDimitry Andric   }
276*0b57cec5SDimitry Andric 
277*0b57cec5SDimitry Andric   return Changed;
278*0b57cec5SDimitry Andric }
279*0b57cec5SDimitry Andric 
280*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
281*0b57cec5SDimitry Andric // MachineOperand iterator
282*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
283*0b57cec5SDimitry Andric 
284*0b57cec5SDimitry Andric MachineOperandIteratorBase::VirtRegInfo
285*0b57cec5SDimitry Andric MachineOperandIteratorBase::analyzeVirtReg(unsigned Reg,
286*0b57cec5SDimitry Andric                     SmallVectorImpl<std::pair<MachineInstr*, unsigned> > *Ops) {
287*0b57cec5SDimitry Andric   VirtRegInfo RI = { false, false, false };
288*0b57cec5SDimitry Andric   for(; isValid(); ++*this) {
289*0b57cec5SDimitry Andric     MachineOperand &MO = deref();
290*0b57cec5SDimitry Andric     if (!MO.isReg() || MO.getReg() != Reg)
291*0b57cec5SDimitry Andric       continue;
292*0b57cec5SDimitry Andric 
293*0b57cec5SDimitry Andric     // Remember each (MI, OpNo) that refers to Reg.
294*0b57cec5SDimitry Andric     if (Ops)
295*0b57cec5SDimitry Andric       Ops->push_back(std::make_pair(MO.getParent(), getOperandNo()));
296*0b57cec5SDimitry Andric 
297*0b57cec5SDimitry Andric     // Both defs and uses can read virtual registers.
298*0b57cec5SDimitry Andric     if (MO.readsReg()) {
299*0b57cec5SDimitry Andric       RI.Reads = true;
300*0b57cec5SDimitry Andric       if (MO.isDef())
301*0b57cec5SDimitry Andric         RI.Tied = true;
302*0b57cec5SDimitry Andric     }
303*0b57cec5SDimitry Andric 
304*0b57cec5SDimitry Andric     // Only defs can write.
305*0b57cec5SDimitry Andric     if (MO.isDef())
306*0b57cec5SDimitry Andric       RI.Writes = true;
307*0b57cec5SDimitry Andric     else if (!RI.Tied && MO.getParent()->isRegTiedToDefOperand(getOperandNo()))
308*0b57cec5SDimitry Andric       RI.Tied = true;
309*0b57cec5SDimitry Andric   }
310*0b57cec5SDimitry Andric   return RI;
311*0b57cec5SDimitry Andric }
312*0b57cec5SDimitry Andric 
313*0b57cec5SDimitry Andric MachineOperandIteratorBase::PhysRegInfo
314*0b57cec5SDimitry Andric MachineOperandIteratorBase::analyzePhysReg(unsigned Reg,
315*0b57cec5SDimitry Andric                                            const TargetRegisterInfo *TRI) {
316*0b57cec5SDimitry Andric   bool AllDefsDead = true;
317*0b57cec5SDimitry Andric   PhysRegInfo PRI = {false, false, false, false, false, false, false, false};
318*0b57cec5SDimitry Andric 
319*0b57cec5SDimitry Andric   assert(TargetRegisterInfo::isPhysicalRegister(Reg) &&
320*0b57cec5SDimitry Andric          "analyzePhysReg not given a physical register!");
321*0b57cec5SDimitry Andric   for (; isValid(); ++*this) {
322*0b57cec5SDimitry Andric     MachineOperand &MO = deref();
323*0b57cec5SDimitry Andric 
324*0b57cec5SDimitry Andric     if (MO.isRegMask() && MO.clobbersPhysReg(Reg)) {
325*0b57cec5SDimitry Andric       PRI.Clobbered = true;
326*0b57cec5SDimitry Andric       continue;
327*0b57cec5SDimitry Andric     }
328*0b57cec5SDimitry Andric 
329*0b57cec5SDimitry Andric     if (!MO.isReg())
330*0b57cec5SDimitry Andric       continue;
331*0b57cec5SDimitry Andric 
332*0b57cec5SDimitry Andric     unsigned MOReg = MO.getReg();
333*0b57cec5SDimitry Andric     if (!MOReg || !TargetRegisterInfo::isPhysicalRegister(MOReg))
334*0b57cec5SDimitry Andric       continue;
335*0b57cec5SDimitry Andric 
336*0b57cec5SDimitry Andric     if (!TRI->regsOverlap(MOReg, Reg))
337*0b57cec5SDimitry Andric       continue;
338*0b57cec5SDimitry Andric 
339*0b57cec5SDimitry Andric     bool Covered = TRI->isSuperRegisterEq(Reg, MOReg);
340*0b57cec5SDimitry Andric     if (MO.readsReg()) {
341*0b57cec5SDimitry Andric       PRI.Read = true;
342*0b57cec5SDimitry Andric       if (Covered) {
343*0b57cec5SDimitry Andric         PRI.FullyRead = true;
344*0b57cec5SDimitry Andric         if (MO.isKill())
345*0b57cec5SDimitry Andric           PRI.Killed = true;
346*0b57cec5SDimitry Andric       }
347*0b57cec5SDimitry Andric     } else if (MO.isDef()) {
348*0b57cec5SDimitry Andric       PRI.Defined = true;
349*0b57cec5SDimitry Andric       if (Covered)
350*0b57cec5SDimitry Andric         PRI.FullyDefined = true;
351*0b57cec5SDimitry Andric       if (!MO.isDead())
352*0b57cec5SDimitry Andric         AllDefsDead = false;
353*0b57cec5SDimitry Andric     }
354*0b57cec5SDimitry Andric   }
355*0b57cec5SDimitry Andric 
356*0b57cec5SDimitry Andric   if (AllDefsDead) {
357*0b57cec5SDimitry Andric     if (PRI.FullyDefined || PRI.Clobbered)
358*0b57cec5SDimitry Andric       PRI.DeadDef = true;
359*0b57cec5SDimitry Andric     else if (PRI.Defined)
360*0b57cec5SDimitry Andric       PRI.PartialDeadDef = true;
361*0b57cec5SDimitry Andric   }
362*0b57cec5SDimitry Andric 
363*0b57cec5SDimitry Andric   return PRI;
364*0b57cec5SDimitry Andric }
365