diff --git a/llvm/include/llvm/CodeGen/MachineInstrBundle.h b/llvm/include/llvm/CodeGen/MachineInstrBundle.h --- a/llvm/include/llvm/CodeGen/MachineInstrBundle.h +++ b/llvm/include/llvm/CodeGen/MachineInstrBundle.h @@ -90,7 +90,10 @@ /// ... /// } /// -class MIBundleOperandIteratorBase { +template +class MIBundleOperandIteratorBase + : public iterator_facade_base, + std::forward_iterator_tag, ValueT> { MachineBasicBlock::instr_iterator InstrI, InstrE; MachineInstr::mop_iterator OpI, OpE; @@ -99,8 +102,10 @@ void advance() { while (OpI == OpE) { // Don't advance off the basic block, or into a new bundle. - if (++InstrI == InstrE || !InstrI->isInsideBundle()) + if (++InstrI == InstrE || !InstrI->isInsideBundle()) { + InstrI = InstrE; break; + } OpI = InstrI->operands_begin(); OpE = InstrI->operands_end(); } @@ -120,7 +125,11 @@ advance(); } - MachineOperand &deref() const { return *OpI; } + /// Constructor for an iterator past the last iteration: both instruction + /// iterators point to the end of the BB and OpI == OpE. + explicit MIBundleOperandIteratorBase(MachineBasicBlock::instr_iterator InstrE, + MachineInstr::mop_iterator OpE) + : InstrI(InstrE), InstrE(InstrE), OpI(OpE), OpE(OpE) {} public: /// isValid - Returns true until all the operands have been visited. @@ -133,6 +142,16 @@ advance(); } + ValueT &operator*() const { return *OpI; } + ValueT *operator->() const { return &*OpI; } + + bool operator==(const MIBundleOperandIteratorBase &Arg) const { + // Iterators are equal, if InstrI matches and either OpIs match or OpI == + // OpE match for both. The second condition allows us to construct an 'end' + // iterator, without finding the last instruction in a bundle up-front. + return InstrI == Arg.InstrI && + (OpI == Arg.OpI || (OpI == OpE && Arg.OpI == Arg.OpE)); + } /// getOperandNo - Returns the number of the current operand relative to its /// instruction. /// @@ -144,24 +163,55 @@ /// MIBundleOperands - Iterate over all operands in a bundle of machine /// instructions. /// -class MIBundleOperands : public MIBundleOperandIteratorBase { +class MIBundleOperands : public MIBundleOperandIteratorBase { + /// Constructor for an iterator past the last iteration. + MIBundleOperands(MachineBasicBlock::instr_iterator InstrE, + MachineInstr::mop_iterator OpE) + : MIBundleOperandIteratorBase(InstrE, OpE) {} + public: MIBundleOperands(MachineInstr &MI) : MIBundleOperandIteratorBase(MI) {} - MachineOperand &operator* () const { return deref(); } - MachineOperand *operator->() const { return &deref(); } + + /// Returns an iterator past the last iteration. + static MIBundleOperands end(const MachineBasicBlock &MBB) { + return {const_cast(MBB).instr_end(), + const_cast(MBB).instr_begin()->operands_end()}; + } }; /// ConstMIBundleOperands - Iterate over all operands in a const bundle of /// machine instructions. /// -class ConstMIBundleOperands : public MIBundleOperandIteratorBase { +class ConstMIBundleOperands + : public MIBundleOperandIteratorBase { + + /// Constructor for an iterator past the last iteration. + ConstMIBundleOperands(MachineBasicBlock::instr_iterator InstrE, + MachineInstr::mop_iterator OpE) + : MIBundleOperandIteratorBase(InstrE, OpE) {} + public: ConstMIBundleOperands(const MachineInstr &MI) : MIBundleOperandIteratorBase(const_cast(MI)) {} - const MachineOperand &operator* () const { return deref(); } - const MachineOperand *operator->() const { return &deref(); } + + /// Returns an iterator past the last iteration. + static ConstMIBundleOperands end(const MachineBasicBlock &MBB) { + return {const_cast(MBB).instr_end(), + const_cast(MBB).instr_begin()->operands_end()}; + } }; +inline iterator_range +const_mi_bundle_ops(const MachineInstr &MI) { + return make_range(ConstMIBundleOperands(MI), + ConstMIBundleOperands::end(*MI.getParent())); +} + +inline iterator_range mi_bundle_ops(MachineInstr &MI) { + return make_range(MIBundleOperands(MI), + MIBundleOperands::end(*MI.getParent())); +} + /// VirtRegInfo - Information about a virtual register used by a set of /// operands. /// diff --git a/llvm/lib/CodeGen/LiveIntervals.cpp b/llvm/lib/CodeGen/LiveIntervals.cpp --- a/llvm/lib/CodeGen/LiveIntervals.cpp +++ b/llvm/lib/CodeGen/LiveIntervals.cpp @@ -1072,9 +1072,9 @@ // Kill flags shouldn't be used while live intervals exist, they will be // reinserted by VirtRegRewriter. if (MachineInstr *KillMI = LIS.getInstructionFromIndex(OldIdxIn->end)) - for (MIBundleOperands MO(*KillMI); MO.isValid(); ++MO) - if (MO->isReg() && MO->isUse()) - MO->setIsKill(false); + for (MachineOperand &MOP : mi_bundle_ops(*KillMI)) + if (MOP.isReg() && MOP.isUse()) + MOP.setIsKill(false); // Is there a def before NewIdx which is not OldIdx? LiveRange::iterator Next = std::next(OldIdxIn);