10b57cec5SDimitry Andric //===- llvm/CodeGen/MachineInstrBundle.h - MI bundle utilities --*- C++ -*-===//
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 // This file provide utility functions to manipulate machine instruction
100b57cec5SDimitry Andric // bundles.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_CODEGEN_MACHINEINSTRBUNDLE_H
150b57cec5SDimitry Andric #define LLVM_CODEGEN_MACHINEINSTRBUNDLE_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric namespace llvm {
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric /// finalizeBundle - Finalize a machine instruction bundle which includes
220b57cec5SDimitry Andric /// a sequence of instructions starting from FirstMI to LastMI (exclusive).
230b57cec5SDimitry Andric /// This routine adds a BUNDLE instruction to represent the bundle, it adds
240b57cec5SDimitry Andric /// IsInternalRead markers to MachineOperands which are defined inside the
250b57cec5SDimitry Andric /// bundle, and it copies externally visible defs and uses to the BUNDLE
260b57cec5SDimitry Andric /// instruction.
270b57cec5SDimitry Andric void finalizeBundle(MachineBasicBlock &MBB,
280b57cec5SDimitry Andric                     MachineBasicBlock::instr_iterator FirstMI,
290b57cec5SDimitry Andric                     MachineBasicBlock::instr_iterator LastMI);
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric /// finalizeBundle - Same functionality as the previous finalizeBundle except
320b57cec5SDimitry Andric /// the last instruction in the bundle is not provided as an input. This is
330b57cec5SDimitry Andric /// used in cases where bundles are pre-determined by marking instructions
340b57cec5SDimitry Andric /// with 'InsideBundle' marker. It returns the MBB instruction iterator that
350b57cec5SDimitry Andric /// points to the end of the bundle.
360b57cec5SDimitry Andric MachineBasicBlock::instr_iterator finalizeBundle(MachineBasicBlock &MBB,
370b57cec5SDimitry Andric                     MachineBasicBlock::instr_iterator FirstMI);
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric /// finalizeBundles - Finalize instruction bundles in the specified
400b57cec5SDimitry Andric /// MachineFunction. Return true if any bundles are finalized.
410b57cec5SDimitry Andric bool finalizeBundles(MachineFunction &MF);
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric /// Returns an iterator to the first instruction in the bundle containing \p I.
getBundleStart(MachineBasicBlock::instr_iterator I)440b57cec5SDimitry Andric inline MachineBasicBlock::instr_iterator getBundleStart(
450b57cec5SDimitry Andric     MachineBasicBlock::instr_iterator I) {
460b57cec5SDimitry Andric   while (I->isBundledWithPred())
470b57cec5SDimitry Andric     --I;
480b57cec5SDimitry Andric   return I;
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric /// Returns an iterator to the first instruction in the bundle containing \p I.
getBundleStart(MachineBasicBlock::const_instr_iterator I)520b57cec5SDimitry Andric inline MachineBasicBlock::const_instr_iterator getBundleStart(
530b57cec5SDimitry Andric     MachineBasicBlock::const_instr_iterator I) {
540b57cec5SDimitry Andric   while (I->isBundledWithPred())
550b57cec5SDimitry Andric     --I;
560b57cec5SDimitry Andric   return I;
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric /// Returns an iterator pointing beyond the bundle containing \p I.
getBundleEnd(MachineBasicBlock::instr_iterator I)600b57cec5SDimitry Andric inline MachineBasicBlock::instr_iterator getBundleEnd(
610b57cec5SDimitry Andric     MachineBasicBlock::instr_iterator I) {
620b57cec5SDimitry Andric   while (I->isBundledWithSucc())
630b57cec5SDimitry Andric     ++I;
640b57cec5SDimitry Andric   ++I;
650b57cec5SDimitry Andric   return I;
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric /// Returns an iterator pointing beyond the bundle containing \p I.
getBundleEnd(MachineBasicBlock::const_instr_iterator I)690b57cec5SDimitry Andric inline MachineBasicBlock::const_instr_iterator getBundleEnd(
700b57cec5SDimitry Andric     MachineBasicBlock::const_instr_iterator I) {
710b57cec5SDimitry Andric   while (I->isBundledWithSucc())
720b57cec5SDimitry Andric     ++I;
730b57cec5SDimitry Andric   ++I;
740b57cec5SDimitry Andric   return I;
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
78480093f4SDimitry Andric // MachineBundleOperand iterator
790b57cec5SDimitry Andric //
800b57cec5SDimitry Andric 
81480093f4SDimitry Andric /// MIBundleOperandIteratorBase - Iterator that visits all operands in a bundle
82480093f4SDimitry Andric /// of MachineInstrs. This class is not intended to be used directly, use one
83480093f4SDimitry Andric /// of the sub-classes instead.
840b57cec5SDimitry Andric ///
850b57cec5SDimitry Andric /// Intended use:
860b57cec5SDimitry Andric ///
870b57cec5SDimitry Andric ///   for (MIBundleOperands MIO(MI); MIO.isValid(); ++MIO) {
880b57cec5SDimitry Andric ///     if (!MIO->isReg())
890b57cec5SDimitry Andric ///       continue;
900b57cec5SDimitry Andric ///     ...
910b57cec5SDimitry Andric ///   }
920b57cec5SDimitry Andric ///
93480093f4SDimitry Andric template <typename ValueT>
94480093f4SDimitry Andric class MIBundleOperandIteratorBase
95480093f4SDimitry Andric     : public iterator_facade_base<MIBundleOperandIteratorBase<ValueT>,
96480093f4SDimitry Andric                                   std::forward_iterator_tag, ValueT> {
970b57cec5SDimitry Andric   MachineBasicBlock::instr_iterator InstrI, InstrE;
980b57cec5SDimitry Andric   MachineInstr::mop_iterator OpI, OpE;
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   // If the operands on InstrI are exhausted, advance InstrI to the next
1010b57cec5SDimitry Andric   // bundled instruction with operands.
advance()1020b57cec5SDimitry Andric   void advance() {
1030b57cec5SDimitry Andric     while (OpI == OpE) {
1040b57cec5SDimitry Andric       // Don't advance off the basic block, or into a new bundle.
105480093f4SDimitry Andric       if (++InstrI == InstrE || !InstrI->isInsideBundle()) {
106480093f4SDimitry Andric         InstrI = InstrE;
1070b57cec5SDimitry Andric         break;
108480093f4SDimitry Andric       }
1090b57cec5SDimitry Andric       OpI = InstrI->operands_begin();
1100b57cec5SDimitry Andric       OpE = InstrI->operands_end();
1110b57cec5SDimitry Andric     }
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric protected:
115480093f4SDimitry Andric   /// MIBundleOperandIteratorBase - Create an iterator that visits all operands
1160b57cec5SDimitry Andric   /// on MI, or all operands on every instruction in the bundle containing MI.
1170b57cec5SDimitry Andric   ///
1180b57cec5SDimitry Andric   /// @param MI The instruction to examine.
1190b57cec5SDimitry Andric   ///
MIBundleOperandIteratorBase(MachineInstr & MI)120480093f4SDimitry Andric   explicit MIBundleOperandIteratorBase(MachineInstr &MI) {
1210b57cec5SDimitry Andric     InstrI = getBundleStart(MI.getIterator());
1220b57cec5SDimitry Andric     InstrE = MI.getParent()->instr_end();
1230b57cec5SDimitry Andric     OpI = InstrI->operands_begin();
1240b57cec5SDimitry Andric     OpE = InstrI->operands_end();
1250b57cec5SDimitry Andric     advance();
1260b57cec5SDimitry Andric   }
1270b57cec5SDimitry Andric 
128480093f4SDimitry Andric   /// Constructor for an iterator past the last iteration: both instruction
129480093f4SDimitry Andric   /// iterators point to the end of the BB and OpI == OpE.
MIBundleOperandIteratorBase(MachineBasicBlock::instr_iterator InstrE,MachineInstr::mop_iterator OpE)130480093f4SDimitry Andric   explicit MIBundleOperandIteratorBase(MachineBasicBlock::instr_iterator InstrE,
131480093f4SDimitry Andric                                        MachineInstr::mop_iterator OpE)
132480093f4SDimitry Andric       : InstrI(InstrE), InstrE(InstrE), OpI(OpE), OpE(OpE) {}
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric public:
1350b57cec5SDimitry Andric   /// isValid - Returns true until all the operands have been visited.
isValid()1360b57cec5SDimitry Andric   bool isValid() const { return OpI != OpE; }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   /// Preincrement.  Move to the next operand.
1390b57cec5SDimitry Andric   void operator++() {
1400b57cec5SDimitry Andric     assert(isValid() && "Cannot advance MIOperands beyond the last operand");
1410b57cec5SDimitry Andric     ++OpI;
1420b57cec5SDimitry Andric     advance();
1430b57cec5SDimitry Andric   }
1440b57cec5SDimitry Andric 
145480093f4SDimitry Andric   ValueT &operator*() const { return *OpI; }
146480093f4SDimitry Andric   ValueT *operator->() const { return &*OpI; }
147480093f4SDimitry Andric 
148480093f4SDimitry Andric   bool operator==(const MIBundleOperandIteratorBase &Arg) const {
149480093f4SDimitry Andric     // Iterators are equal, if InstrI matches and either OpIs match or OpI ==
150480093f4SDimitry Andric     // OpE match for both. The second condition allows us to construct an 'end'
151480093f4SDimitry Andric     // iterator, without finding the last instruction in a bundle up-front.
152480093f4SDimitry Andric     return InstrI == Arg.InstrI &&
153480093f4SDimitry Andric            (OpI == Arg.OpI || (OpI == OpE && Arg.OpI == Arg.OpE));
154480093f4SDimitry Andric   }
1550b57cec5SDimitry Andric   /// getOperandNo - Returns the number of the current operand relative to its
1560b57cec5SDimitry Andric   /// instruction.
1570b57cec5SDimitry Andric   ///
getOperandNo()1580b57cec5SDimitry Andric   unsigned getOperandNo() const {
1590b57cec5SDimitry Andric     return OpI - InstrI->operands_begin();
1600b57cec5SDimitry Andric   }
161480093f4SDimitry Andric };
1620b57cec5SDimitry Andric 
163480093f4SDimitry Andric /// MIBundleOperands - Iterate over all operands in a bundle of machine
164480093f4SDimitry Andric /// instructions.
165480093f4SDimitry Andric ///
166480093f4SDimitry Andric class MIBundleOperands : public MIBundleOperandIteratorBase<MachineOperand> {
167480093f4SDimitry Andric   /// Constructor for an iterator past the last iteration.
MIBundleOperands(MachineBasicBlock::instr_iterator InstrE,MachineInstr::mop_iterator OpE)168480093f4SDimitry Andric   MIBundleOperands(MachineBasicBlock::instr_iterator InstrE,
169480093f4SDimitry Andric                    MachineInstr::mop_iterator OpE)
170480093f4SDimitry Andric       : MIBundleOperandIteratorBase(InstrE, OpE) {}
171480093f4SDimitry Andric 
172480093f4SDimitry Andric public:
MIBundleOperands(MachineInstr & MI)173480093f4SDimitry Andric   MIBundleOperands(MachineInstr &MI) : MIBundleOperandIteratorBase(MI) {}
174480093f4SDimitry Andric 
175480093f4SDimitry Andric   /// Returns an iterator past the last iteration.
end(const MachineBasicBlock & MBB)176480093f4SDimitry Andric   static MIBundleOperands end(const MachineBasicBlock &MBB) {
177480093f4SDimitry Andric     return {const_cast<MachineBasicBlock &>(MBB).instr_end(),
178480093f4SDimitry Andric             const_cast<MachineBasicBlock &>(MBB).instr_begin()->operands_end()};
179480093f4SDimitry Andric   }
180480093f4SDimitry Andric };
181480093f4SDimitry Andric 
182480093f4SDimitry Andric /// ConstMIBundleOperands - Iterate over all operands in a const bundle of
183480093f4SDimitry Andric /// machine instructions.
184480093f4SDimitry Andric ///
185480093f4SDimitry Andric class ConstMIBundleOperands
186480093f4SDimitry Andric     : public MIBundleOperandIteratorBase<const MachineOperand> {
187480093f4SDimitry Andric 
188480093f4SDimitry Andric   /// Constructor for an iterator past the last iteration.
ConstMIBundleOperands(MachineBasicBlock::instr_iterator InstrE,MachineInstr::mop_iterator OpE)189480093f4SDimitry Andric   ConstMIBundleOperands(MachineBasicBlock::instr_iterator InstrE,
190480093f4SDimitry Andric                         MachineInstr::mop_iterator OpE)
191480093f4SDimitry Andric       : MIBundleOperandIteratorBase(InstrE, OpE) {}
192480093f4SDimitry Andric 
193480093f4SDimitry Andric public:
ConstMIBundleOperands(const MachineInstr & MI)194480093f4SDimitry Andric   ConstMIBundleOperands(const MachineInstr &MI)
195480093f4SDimitry Andric       : MIBundleOperandIteratorBase(const_cast<MachineInstr &>(MI)) {}
196480093f4SDimitry Andric 
197480093f4SDimitry Andric   /// Returns an iterator past the last iteration.
end(const MachineBasicBlock & MBB)198480093f4SDimitry Andric   static ConstMIBundleOperands end(const MachineBasicBlock &MBB) {
199480093f4SDimitry Andric     return {const_cast<MachineBasicBlock &>(MBB).instr_end(),
200480093f4SDimitry Andric             const_cast<MachineBasicBlock &>(MBB).instr_begin()->operands_end()};
201480093f4SDimitry Andric   }
202480093f4SDimitry Andric };
203480093f4SDimitry Andric 
204480093f4SDimitry Andric inline iterator_range<ConstMIBundleOperands>
const_mi_bundle_ops(const MachineInstr & MI)205480093f4SDimitry Andric const_mi_bundle_ops(const MachineInstr &MI) {
206480093f4SDimitry Andric   return make_range(ConstMIBundleOperands(MI),
207480093f4SDimitry Andric                     ConstMIBundleOperands::end(*MI.getParent()));
208480093f4SDimitry Andric }
209480093f4SDimitry Andric 
mi_bundle_ops(MachineInstr & MI)210480093f4SDimitry Andric inline iterator_range<MIBundleOperands> mi_bundle_ops(MachineInstr &MI) {
211480093f4SDimitry Andric   return make_range(MIBundleOperands(MI),
212480093f4SDimitry Andric                     MIBundleOperands::end(*MI.getParent()));
213480093f4SDimitry Andric }
214480093f4SDimitry Andric 
215480093f4SDimitry Andric /// VirtRegInfo - Information about a virtual register used by a set of
216480093f4SDimitry Andric /// operands.
2170b57cec5SDimitry Andric ///
2180b57cec5SDimitry Andric struct VirtRegInfo {
2190b57cec5SDimitry Andric   /// Reads - One of the operands read the virtual register.  This does not
2200b57cec5SDimitry Andric   /// include undef or internal use operands, see MO::readsReg().
2210b57cec5SDimitry Andric   bool Reads;
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   /// Writes - One of the operands writes the virtual register.
2240b57cec5SDimitry Andric   bool Writes;
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   /// Tied - Uses and defs must use the same register. This can be because of
2270b57cec5SDimitry Andric   /// a two-address constraint, or there may be a partial redefinition of a
2280b57cec5SDimitry Andric   /// sub-register.
2290b57cec5SDimitry Andric   bool Tied;
2300b57cec5SDimitry Andric };
2310b57cec5SDimitry Andric 
232480093f4SDimitry Andric /// AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses
233480093f4SDimitry Andric /// a virtual register.  This function should not be called after operator++(),
234480093f4SDimitry Andric /// it expects a fresh iterator.
235480093f4SDimitry Andric ///
236480093f4SDimitry Andric /// @param Reg The virtual register to analyze.
237480093f4SDimitry Andric /// @param Ops When set, this vector will receive an (MI, OpNum) entry for
238480093f4SDimitry Andric ///            each operand referring to Reg.
239480093f4SDimitry Andric /// @returns A filled-in RegInfo struct.
240480093f4SDimitry Andric VirtRegInfo AnalyzeVirtRegInBundle(
2415ffd83dbSDimitry Andric     MachineInstr &MI, Register Reg,
242480093f4SDimitry Andric     SmallVectorImpl<std::pair<MachineInstr *, unsigned>> *Ops = nullptr);
243480093f4SDimitry Andric 
24406c3fb27SDimitry Andric /// Return a pair of lane masks (reads, writes) indicating which lanes this
24506c3fb27SDimitry Andric /// instruction uses with Reg.
24606c3fb27SDimitry Andric std::pair<LaneBitmask, LaneBitmask>
24706c3fb27SDimitry Andric AnalyzeVirtRegLanesInBundle(const MachineInstr &MI, Register Reg,
24806c3fb27SDimitry Andric                             const MachineRegisterInfo &MRI,
24906c3fb27SDimitry Andric                             const TargetRegisterInfo &TRI);
25006c3fb27SDimitry Andric 
2510b57cec5SDimitry Andric /// Information about how a physical register Reg is used by a set of
2520b57cec5SDimitry Andric /// operands.
2530b57cec5SDimitry Andric struct PhysRegInfo {
2540b57cec5SDimitry Andric   /// There is a regmask operand indicating Reg is clobbered.
2550b57cec5SDimitry Andric   /// \see MachineOperand::CreateRegMask().
2560b57cec5SDimitry Andric   bool Clobbered;
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   /// Reg or one of its aliases is defined. The definition may only cover
2590b57cec5SDimitry Andric   /// parts of the register.
2600b57cec5SDimitry Andric   bool Defined;
2610b57cec5SDimitry Andric   /// Reg or a super-register is defined. The definition covers the full
2620b57cec5SDimitry Andric   /// register.
2630b57cec5SDimitry Andric   bool FullyDefined;
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   /// Reg or one of its aliases is read. The register may only be read
2660b57cec5SDimitry Andric   /// partially.
2670b57cec5SDimitry Andric   bool Read;
2680b57cec5SDimitry Andric   /// Reg or a super-register is read. The full register is read.
2690b57cec5SDimitry Andric   bool FullyRead;
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   /// Either:
2720b57cec5SDimitry Andric   /// - Reg is FullyDefined and all defs of reg or an overlapping
2730b57cec5SDimitry Andric   ///   register are dead, or
2740b57cec5SDimitry Andric   /// - Reg is completely dead because "defined" by a clobber.
2750b57cec5SDimitry Andric   bool DeadDef;
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric   /// Reg is Defined and all defs of reg or an overlapping register are
2780b57cec5SDimitry Andric   /// dead.
2790b57cec5SDimitry Andric   bool PartialDeadDef;
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   /// There is a use operand of reg or a super-register with kill flag set.
2820b57cec5SDimitry Andric   bool Killed;
2830b57cec5SDimitry Andric };
2840b57cec5SDimitry Andric 
285480093f4SDimitry Andric /// AnalyzePhysRegInBundle - Analyze how the current instruction or bundle uses
286480093f4SDimitry Andric /// a physical register.  This function should not be called after operator++(),
2870b57cec5SDimitry Andric /// it expects a fresh iterator.
2880b57cec5SDimitry Andric ///
2890b57cec5SDimitry Andric /// @param Reg The physical register to analyze.
2900b57cec5SDimitry Andric /// @returns A filled-in PhysRegInfo struct.
2915ffd83dbSDimitry Andric PhysRegInfo AnalyzePhysRegInBundle(const MachineInstr &MI, Register Reg,
292480093f4SDimitry Andric                                    const TargetRegisterInfo *TRI);
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric } // End llvm namespace
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric #endif
297