xref: /freebsd/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineInstrBundle.h (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- llvm/CodeGen/MachineInstrBundle.h - MI bundle utilities --*- C++ -*-===//
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 // This file provide utility functions to manipulate machine instruction
10*0b57cec5SDimitry Andric // bundles.
11*0b57cec5SDimitry Andric //
12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric #ifndef LLVM_CODEGEN_MACHINEINSTRBUNDLE_H
15*0b57cec5SDimitry Andric #define LLVM_CODEGEN_MACHINEINSTRBUNDLE_H
16*0b57cec5SDimitry Andric 
17*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
18*0b57cec5SDimitry Andric 
19*0b57cec5SDimitry Andric namespace llvm {
20*0b57cec5SDimitry Andric 
21*0b57cec5SDimitry Andric /// finalizeBundle - Finalize a machine instruction bundle which includes
22*0b57cec5SDimitry Andric /// a sequence of instructions starting from FirstMI to LastMI (exclusive).
23*0b57cec5SDimitry Andric /// This routine adds a BUNDLE instruction to represent the bundle, it adds
24*0b57cec5SDimitry Andric /// IsInternalRead markers to MachineOperands which are defined inside the
25*0b57cec5SDimitry Andric /// bundle, and it copies externally visible defs and uses to the BUNDLE
26*0b57cec5SDimitry Andric /// instruction.
27*0b57cec5SDimitry Andric void finalizeBundle(MachineBasicBlock &MBB,
28*0b57cec5SDimitry Andric                     MachineBasicBlock::instr_iterator FirstMI,
29*0b57cec5SDimitry Andric                     MachineBasicBlock::instr_iterator LastMI);
30*0b57cec5SDimitry Andric 
31*0b57cec5SDimitry Andric /// finalizeBundle - Same functionality as the previous finalizeBundle except
32*0b57cec5SDimitry Andric /// the last instruction in the bundle is not provided as an input. This is
33*0b57cec5SDimitry Andric /// used in cases where bundles are pre-determined by marking instructions
34*0b57cec5SDimitry Andric /// with 'InsideBundle' marker. It returns the MBB instruction iterator that
35*0b57cec5SDimitry Andric /// points to the end of the bundle.
36*0b57cec5SDimitry Andric MachineBasicBlock::instr_iterator finalizeBundle(MachineBasicBlock &MBB,
37*0b57cec5SDimitry Andric                     MachineBasicBlock::instr_iterator FirstMI);
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric /// finalizeBundles - Finalize instruction bundles in the specified
40*0b57cec5SDimitry Andric /// MachineFunction. Return true if any bundles are finalized.
41*0b57cec5SDimitry Andric bool finalizeBundles(MachineFunction &MF);
42*0b57cec5SDimitry Andric 
43*0b57cec5SDimitry Andric /// Returns an iterator to the first instruction in the bundle containing \p I.
44*0b57cec5SDimitry Andric inline MachineBasicBlock::instr_iterator getBundleStart(
45*0b57cec5SDimitry Andric     MachineBasicBlock::instr_iterator I) {
46*0b57cec5SDimitry Andric   while (I->isBundledWithPred())
47*0b57cec5SDimitry Andric     --I;
48*0b57cec5SDimitry Andric   return I;
49*0b57cec5SDimitry Andric }
50*0b57cec5SDimitry Andric 
51*0b57cec5SDimitry Andric /// Returns an iterator to the first instruction in the bundle containing \p I.
52*0b57cec5SDimitry Andric inline MachineBasicBlock::const_instr_iterator getBundleStart(
53*0b57cec5SDimitry Andric     MachineBasicBlock::const_instr_iterator I) {
54*0b57cec5SDimitry Andric   while (I->isBundledWithPred())
55*0b57cec5SDimitry Andric     --I;
56*0b57cec5SDimitry Andric   return I;
57*0b57cec5SDimitry Andric }
58*0b57cec5SDimitry Andric 
59*0b57cec5SDimitry Andric /// Returns an iterator pointing beyond the bundle containing \p I.
60*0b57cec5SDimitry Andric inline MachineBasicBlock::instr_iterator getBundleEnd(
61*0b57cec5SDimitry Andric     MachineBasicBlock::instr_iterator I) {
62*0b57cec5SDimitry Andric   while (I->isBundledWithSucc())
63*0b57cec5SDimitry Andric     ++I;
64*0b57cec5SDimitry Andric   ++I;
65*0b57cec5SDimitry Andric   return I;
66*0b57cec5SDimitry Andric }
67*0b57cec5SDimitry Andric 
68*0b57cec5SDimitry Andric /// Returns an iterator pointing beyond the bundle containing \p I.
69*0b57cec5SDimitry Andric inline MachineBasicBlock::const_instr_iterator getBundleEnd(
70*0b57cec5SDimitry Andric     MachineBasicBlock::const_instr_iterator I) {
71*0b57cec5SDimitry Andric   while (I->isBundledWithSucc())
72*0b57cec5SDimitry Andric     ++I;
73*0b57cec5SDimitry Andric   ++I;
74*0b57cec5SDimitry Andric   return I;
75*0b57cec5SDimitry Andric }
76*0b57cec5SDimitry Andric 
77*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
78*0b57cec5SDimitry Andric // MachineOperand iterator
79*0b57cec5SDimitry Andric //
80*0b57cec5SDimitry Andric 
81*0b57cec5SDimitry Andric /// MachineOperandIteratorBase - Iterator that can visit all operands on a
82*0b57cec5SDimitry Andric /// MachineInstr, or all operands on a bundle of MachineInstrs.  This class is
83*0b57cec5SDimitry Andric /// not intended to be used directly, use one of the sub-classes instead.
84*0b57cec5SDimitry Andric ///
85*0b57cec5SDimitry Andric /// Intended use:
86*0b57cec5SDimitry Andric ///
87*0b57cec5SDimitry Andric ///   for (MIBundleOperands MIO(MI); MIO.isValid(); ++MIO) {
88*0b57cec5SDimitry Andric ///     if (!MIO->isReg())
89*0b57cec5SDimitry Andric ///       continue;
90*0b57cec5SDimitry Andric ///     ...
91*0b57cec5SDimitry Andric ///   }
92*0b57cec5SDimitry Andric ///
93*0b57cec5SDimitry Andric class MachineOperandIteratorBase {
94*0b57cec5SDimitry Andric   MachineBasicBlock::instr_iterator InstrI, InstrE;
95*0b57cec5SDimitry Andric   MachineInstr::mop_iterator OpI, OpE;
96*0b57cec5SDimitry Andric 
97*0b57cec5SDimitry Andric   // If the operands on InstrI are exhausted, advance InstrI to the next
98*0b57cec5SDimitry Andric   // bundled instruction with operands.
99*0b57cec5SDimitry Andric   void advance() {
100*0b57cec5SDimitry Andric     while (OpI == OpE) {
101*0b57cec5SDimitry Andric       // Don't advance off the basic block, or into a new bundle.
102*0b57cec5SDimitry Andric       if (++InstrI == InstrE || !InstrI->isInsideBundle())
103*0b57cec5SDimitry Andric         break;
104*0b57cec5SDimitry Andric       OpI = InstrI->operands_begin();
105*0b57cec5SDimitry Andric       OpE = InstrI->operands_end();
106*0b57cec5SDimitry Andric     }
107*0b57cec5SDimitry Andric   }
108*0b57cec5SDimitry Andric 
109*0b57cec5SDimitry Andric protected:
110*0b57cec5SDimitry Andric   /// MachineOperandIteratorBase - Create an iterator that visits all operands
111*0b57cec5SDimitry Andric   /// on MI, or all operands on every instruction in the bundle containing MI.
112*0b57cec5SDimitry Andric   ///
113*0b57cec5SDimitry Andric   /// @param MI The instruction to examine.
114*0b57cec5SDimitry Andric   /// @param WholeBundle When true, visit all operands on the entire bundle.
115*0b57cec5SDimitry Andric   ///
116*0b57cec5SDimitry Andric   explicit MachineOperandIteratorBase(MachineInstr &MI, bool WholeBundle) {
117*0b57cec5SDimitry Andric     if (WholeBundle) {
118*0b57cec5SDimitry Andric       InstrI = getBundleStart(MI.getIterator());
119*0b57cec5SDimitry Andric       InstrE = MI.getParent()->instr_end();
120*0b57cec5SDimitry Andric     } else {
121*0b57cec5SDimitry Andric       InstrI = InstrE = MI.getIterator();
122*0b57cec5SDimitry Andric       ++InstrE;
123*0b57cec5SDimitry Andric     }
124*0b57cec5SDimitry Andric     OpI = InstrI->operands_begin();
125*0b57cec5SDimitry Andric     OpE = InstrI->operands_end();
126*0b57cec5SDimitry Andric     if (WholeBundle)
127*0b57cec5SDimitry Andric       advance();
128*0b57cec5SDimitry Andric   }
129*0b57cec5SDimitry Andric 
130*0b57cec5SDimitry Andric   MachineOperand &deref() const { return *OpI; }
131*0b57cec5SDimitry Andric 
132*0b57cec5SDimitry Andric public:
133*0b57cec5SDimitry Andric   /// isValid - Returns true until all the operands have been visited.
134*0b57cec5SDimitry Andric   bool isValid() const { return OpI != OpE; }
135*0b57cec5SDimitry Andric 
136*0b57cec5SDimitry Andric   /// Preincrement.  Move to the next operand.
137*0b57cec5SDimitry Andric   void operator++() {
138*0b57cec5SDimitry Andric     assert(isValid() && "Cannot advance MIOperands beyond the last operand");
139*0b57cec5SDimitry Andric     ++OpI;
140*0b57cec5SDimitry Andric     advance();
141*0b57cec5SDimitry Andric   }
142*0b57cec5SDimitry Andric 
143*0b57cec5SDimitry Andric   /// getOperandNo - Returns the number of the current operand relative to its
144*0b57cec5SDimitry Andric   /// instruction.
145*0b57cec5SDimitry Andric   ///
146*0b57cec5SDimitry Andric   unsigned getOperandNo() const {
147*0b57cec5SDimitry Andric     return OpI - InstrI->operands_begin();
148*0b57cec5SDimitry Andric   }
149*0b57cec5SDimitry Andric 
150*0b57cec5SDimitry Andric   /// VirtRegInfo - Information about a virtual register used by a set of operands.
151*0b57cec5SDimitry Andric   ///
152*0b57cec5SDimitry Andric   struct VirtRegInfo {
153*0b57cec5SDimitry Andric     /// Reads - One of the operands read the virtual register.  This does not
154*0b57cec5SDimitry Andric     /// include undef or internal use operands, see MO::readsReg().
155*0b57cec5SDimitry Andric     bool Reads;
156*0b57cec5SDimitry Andric 
157*0b57cec5SDimitry Andric     /// Writes - One of the operands writes the virtual register.
158*0b57cec5SDimitry Andric     bool Writes;
159*0b57cec5SDimitry Andric 
160*0b57cec5SDimitry Andric     /// Tied - Uses and defs must use the same register. This can be because of
161*0b57cec5SDimitry Andric     /// a two-address constraint, or there may be a partial redefinition of a
162*0b57cec5SDimitry Andric     /// sub-register.
163*0b57cec5SDimitry Andric     bool Tied;
164*0b57cec5SDimitry Andric   };
165*0b57cec5SDimitry Andric 
166*0b57cec5SDimitry Andric   /// Information about how a physical register Reg is used by a set of
167*0b57cec5SDimitry Andric   /// operands.
168*0b57cec5SDimitry Andric   struct PhysRegInfo {
169*0b57cec5SDimitry Andric     /// There is a regmask operand indicating Reg is clobbered.
170*0b57cec5SDimitry Andric     /// \see MachineOperand::CreateRegMask().
171*0b57cec5SDimitry Andric     bool Clobbered;
172*0b57cec5SDimitry Andric 
173*0b57cec5SDimitry Andric     /// Reg or one of its aliases is defined. The definition may only cover
174*0b57cec5SDimitry Andric     /// parts of the register.
175*0b57cec5SDimitry Andric     bool Defined;
176*0b57cec5SDimitry Andric     /// Reg or a super-register is defined. The definition covers the full
177*0b57cec5SDimitry Andric     /// register.
178*0b57cec5SDimitry Andric     bool FullyDefined;
179*0b57cec5SDimitry Andric 
180*0b57cec5SDimitry Andric     /// Reg or one of its aliases is read. The register may only be read
181*0b57cec5SDimitry Andric     /// partially.
182*0b57cec5SDimitry Andric     bool Read;
183*0b57cec5SDimitry Andric     /// Reg or a super-register is read. The full register is read.
184*0b57cec5SDimitry Andric     bool FullyRead;
185*0b57cec5SDimitry Andric 
186*0b57cec5SDimitry Andric     /// Either:
187*0b57cec5SDimitry Andric     /// - Reg is FullyDefined and all defs of reg or an overlapping
188*0b57cec5SDimitry Andric     ///   register are dead, or
189*0b57cec5SDimitry Andric     /// - Reg is completely dead because "defined" by a clobber.
190*0b57cec5SDimitry Andric     bool DeadDef;
191*0b57cec5SDimitry Andric 
192*0b57cec5SDimitry Andric     /// Reg is Defined and all defs of reg or an overlapping register are
193*0b57cec5SDimitry Andric     /// dead.
194*0b57cec5SDimitry Andric     bool PartialDeadDef;
195*0b57cec5SDimitry Andric 
196*0b57cec5SDimitry Andric     /// There is a use operand of reg or a super-register with kill flag set.
197*0b57cec5SDimitry Andric     bool Killed;
198*0b57cec5SDimitry Andric   };
199*0b57cec5SDimitry Andric 
200*0b57cec5SDimitry Andric   /// analyzeVirtReg - Analyze how the current instruction or bundle uses a
201*0b57cec5SDimitry Andric   /// virtual register.  This function should not be called after operator++(),
202*0b57cec5SDimitry Andric   /// it expects a fresh iterator.
203*0b57cec5SDimitry Andric   ///
204*0b57cec5SDimitry Andric   /// @param Reg The virtual register to analyze.
205*0b57cec5SDimitry Andric   /// @param Ops When set, this vector will receive an (MI, OpNum) entry for
206*0b57cec5SDimitry Andric   ///            each operand referring to Reg.
207*0b57cec5SDimitry Andric   /// @returns A filled-in RegInfo struct.
208*0b57cec5SDimitry Andric   VirtRegInfo analyzeVirtReg(unsigned Reg,
209*0b57cec5SDimitry Andric            SmallVectorImpl<std::pair<MachineInstr*, unsigned> > *Ops = nullptr);
210*0b57cec5SDimitry Andric 
211*0b57cec5SDimitry Andric   /// analyzePhysReg - Analyze how the current instruction or bundle uses a
212*0b57cec5SDimitry Andric   /// physical register.  This function should not be called after operator++(),
213*0b57cec5SDimitry Andric   /// it expects a fresh iterator.
214*0b57cec5SDimitry Andric   ///
215*0b57cec5SDimitry Andric   /// @param Reg The physical register to analyze.
216*0b57cec5SDimitry Andric   /// @returns A filled-in PhysRegInfo struct.
217*0b57cec5SDimitry Andric   PhysRegInfo analyzePhysReg(unsigned Reg, const TargetRegisterInfo *TRI);
218*0b57cec5SDimitry Andric };
219*0b57cec5SDimitry Andric 
220*0b57cec5SDimitry Andric /// MIOperands - Iterate over operands of a single instruction.
221*0b57cec5SDimitry Andric ///
222*0b57cec5SDimitry Andric class MIOperands : public MachineOperandIteratorBase {
223*0b57cec5SDimitry Andric public:
224*0b57cec5SDimitry Andric   MIOperands(MachineInstr &MI) : MachineOperandIteratorBase(MI, false) {}
225*0b57cec5SDimitry Andric   MachineOperand &operator* () const { return deref(); }
226*0b57cec5SDimitry Andric   MachineOperand *operator->() const { return &deref(); }
227*0b57cec5SDimitry Andric };
228*0b57cec5SDimitry Andric 
229*0b57cec5SDimitry Andric /// ConstMIOperands - Iterate over operands of a single const instruction.
230*0b57cec5SDimitry Andric ///
231*0b57cec5SDimitry Andric class ConstMIOperands : public MachineOperandIteratorBase {
232*0b57cec5SDimitry Andric public:
233*0b57cec5SDimitry Andric   ConstMIOperands(const MachineInstr &MI)
234*0b57cec5SDimitry Andric       : MachineOperandIteratorBase(const_cast<MachineInstr &>(MI), false) {}
235*0b57cec5SDimitry Andric   const MachineOperand &operator* () const { return deref(); }
236*0b57cec5SDimitry Andric   const MachineOperand *operator->() const { return &deref(); }
237*0b57cec5SDimitry Andric };
238*0b57cec5SDimitry Andric 
239*0b57cec5SDimitry Andric /// MIBundleOperands - Iterate over all operands in a bundle of machine
240*0b57cec5SDimitry Andric /// instructions.
241*0b57cec5SDimitry Andric ///
242*0b57cec5SDimitry Andric class MIBundleOperands : public MachineOperandIteratorBase {
243*0b57cec5SDimitry Andric public:
244*0b57cec5SDimitry Andric   MIBundleOperands(MachineInstr &MI) : MachineOperandIteratorBase(MI, true) {}
245*0b57cec5SDimitry Andric   MachineOperand &operator* () const { return deref(); }
246*0b57cec5SDimitry Andric   MachineOperand *operator->() const { return &deref(); }
247*0b57cec5SDimitry Andric };
248*0b57cec5SDimitry Andric 
249*0b57cec5SDimitry Andric /// ConstMIBundleOperands - Iterate over all operands in a const bundle of
250*0b57cec5SDimitry Andric /// machine instructions.
251*0b57cec5SDimitry Andric ///
252*0b57cec5SDimitry Andric class ConstMIBundleOperands : public MachineOperandIteratorBase {
253*0b57cec5SDimitry Andric public:
254*0b57cec5SDimitry Andric   ConstMIBundleOperands(const MachineInstr &MI)
255*0b57cec5SDimitry Andric       : MachineOperandIteratorBase(const_cast<MachineInstr &>(MI), true) {}
256*0b57cec5SDimitry Andric   const MachineOperand &operator* () const { return deref(); }
257*0b57cec5SDimitry Andric   const MachineOperand *operator->() const { return &deref(); }
258*0b57cec5SDimitry Andric };
259*0b57cec5SDimitry Andric 
260*0b57cec5SDimitry Andric } // End llvm namespace
261*0b57cec5SDimitry Andric 
262*0b57cec5SDimitry Andric #endif
263