diff --git a/llvm/include/llvm/MC/MCRegisterInfo.h b/llvm/include/llvm/MC/MCRegisterInfo.h --- a/llvm/include/llvm/MC/MCRegisterInfo.h +++ b/llvm/include/llvm/MC/MCRegisterInfo.h @@ -16,11 +16,13 @@ #define LLVM_MC_MCREGISTERINFO_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include "llvm/MC/LaneBitmask.h" #include "llvm/MC/MCRegister.h" #include #include +#include #include namespace llvm { @@ -177,6 +179,9 @@ DenseMap L2CVRegs; // LLVM to CV regs mapping public: + // Forward declaration to become a friend class of DiffListIterator. + template class mc_difflist_iterator; + /// DiffListIterator - Base iterator class that can traverse the /// differentially encoded register and regunit lists in DiffLists. /// Don't use this class directly, use one of the specialized sub-classes @@ -220,8 +225,105 @@ if (!advance()) List = nullptr; } + + template friend class MCRegisterInfo::mc_difflist_iterator; }; + /// Forward iterator using DiffListIterator. + template + class mc_difflist_iterator + : public iterator_facade_base, + std::forward_iterator_tag, MCPhysReg> { + MCRegisterInfo::DiffListIterator Iter; + /// Current value as MCPhysReg, so we can return a reference to it. + MCPhysReg Val; + + protected: + mc_difflist_iterator(MCRegisterInfo::DiffListIterator Iter) : Iter(Iter) {} + + // Allow conversion between instantiations where valid. + mc_difflist_iterator(MCRegister Reg, const MCPhysReg *DiffList) { + Iter.init(Reg, DiffList); + Val = *Iter; + } + + public: + // Allow default construction to build variables, but this doesn't build + // a useful iterator. + mc_difflist_iterator() = default; + + /// Return an iterator past the last element. + static SubT end() { + SubT End; + End.Iter.List = nullptr; + return End; + } + + bool operator==(const mc_difflist_iterator &Arg) const { + return Iter.List == Arg.Iter.List; + } + + const MCPhysReg &operator*() const { return Val; } + + using mc_difflist_iterator::iterator_facade_base::operator++; + void operator++() { + assert(Iter.List && "Cannot increment the end iterator!"); + ++Iter; + Val = *Iter; + } + }; + + /// Forward iterator over all sub-registers. + /// TODO: Replace remaining uses of MCSubRegIterator. + class mc_subreg_iterator : public mc_difflist_iterator { + public: + mc_subreg_iterator(MCRegisterInfo::DiffListIterator Iter) + : mc_difflist_iterator(Iter) {} + mc_subreg_iterator() = default; + mc_subreg_iterator(MCRegister Reg, const MCRegisterInfo *MCRI) + : mc_difflist_iterator(Reg, MCRI->DiffLists + MCRI->get(Reg).SubRegs) {} + }; + + /// Forward iterator over all super-registers. + /// TODO: Replace remaining uses of MCSuperRegIterator. + class mc_superreg_iterator + : public mc_difflist_iterator { + public: + mc_superreg_iterator(MCRegisterInfo::DiffListIterator Iter) + : mc_difflist_iterator(Iter) {} + mc_superreg_iterator() = default; + mc_superreg_iterator(MCRegister Reg, const MCRegisterInfo *MCRI) + : mc_difflist_iterator(Reg, + MCRI->DiffLists + MCRI->get(Reg).SuperRegs) {} + }; + + /// Return an iterator range over all sub-registers of \p Reg, excluding \p + /// Reg. + iterator_range subregs(MCRegister Reg) const { + return make_range(std::next(mc_subreg_iterator(Reg, this)), + mc_subreg_iterator::end()); + } + + /// Return an iterator range over all sub-registers of \p Reg, including \p + /// Reg. + iterator_range subregs_inclusive(MCRegister Reg) const { + return make_range({Reg, this}, mc_subreg_iterator::end()); + } + + /// Return an iterator range over all super-registers of \p Reg, excluding \p + /// Reg. + iterator_range superregs(MCRegister Reg) const { + return make_range(std::next(mc_superreg_iterator(Reg, this)), + mc_superreg_iterator::end()); + } + + /// Return an iterator range over all super-registers of \p Reg, including \p + /// Reg. + iterator_range + superregs_inclusive(MCRegister Reg) const { + return make_range({Reg, this}, mc_superreg_iterator::end()); + } + // These iterators are allowed to sub-class DiffListIterator and access // internal list pointers. friend class MCSubRegIterator; diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -124,8 +124,8 @@ void addRegWithSubRegs(RegVector &RV, unsigned Reg) { RV.push_back(Reg); if (Register::isPhysicalRegister(Reg)) - for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs) - RV.push_back(*SubRegs); + for (const MCPhysReg &SubReg : TRI->subregs(Reg)) + RV.push_back(SubReg); } struct BBInfo { @@ -802,18 +802,16 @@ report("MBB live-in list contains non-physical register", MBB); continue; } - for (MCSubRegIterator SubRegs(LI.PhysReg, TRI, /*IncludeSelf=*/true); - SubRegs.isValid(); ++SubRegs) - regsLive.insert(*SubRegs); + for (const MCPhysReg &SubReg : TRI->subregs_inclusive(LI.PhysReg)) + regsLive.insert(SubReg); } } const MachineFrameInfo &MFI = MF->getFrameInfo(); BitVector PR = MFI.getPristineRegs(*MF); for (unsigned I : PR.set_bits()) { - for (MCSubRegIterator SubRegs(I, TRI, /*IncludeSelf=*/true); - SubRegs.isValid(); ++SubRegs) - regsLive.insert(*SubRegs); + for (const MCPhysReg &SubReg : TRI->subregs_inclusive(I)) + regsLive.insert(SubReg); } regsKilled.clear(); @@ -2006,9 +2004,9 @@ bool Bad = !isReserved(Reg); // We are fine if just any subregister has a defined value. if (Bad) { - for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); - ++SubRegs) { - if (regsLive.count(*SubRegs)) { + + for (const MCPhysReg &SubReg : TRI->subregs(Reg)) { + if (regsLive.count(SubReg)) { Bad = false; break; } @@ -2026,9 +2024,8 @@ if (!Register::isPhysicalRegister(MOP.getReg())) continue; - for (MCSubRegIterator SubRegs(MOP.getReg(), TRI); SubRegs.isValid(); - ++SubRegs) { - if (*SubRegs == Reg) { + for (const MCPhysReg &SubReg : TRI->subregs(MOP.getReg())) { + if (SubReg == Reg) { Bad = false; break; } diff --git a/llvm/lib/CodeGen/RegisterScavenging.cpp b/llvm/lib/CodeGen/RegisterScavenging.cpp --- a/llvm/lib/CodeGen/RegisterScavenging.cpp +++ b/llvm/lib/CodeGen/RegisterScavenging.cpp @@ -221,8 +221,8 @@ // Ideally we would like a way to model this, but leaving the // insert_subreg around causes both correctness and performance issues. bool SubUsed = false; - for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs) - if (isRegUsed(*SubRegs)) { + for (const MCPhysReg &SubReg : TRI->subregs(Reg)) + if (isRegUsed(SubReg)) { SubUsed = true; break; } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp @@ -74,27 +74,23 @@ const MCRegisterInfo *MCRegInfo) { unsigned Value = 0; - for (MCSubRegIterator SubRegIt(Reg, MCRegInfo, true); SubRegIt.isValid(); - ++SubRegIt) { - unsigned CurrentSubReg = *SubRegIt; - - unsigned EncVal = MCRegInfo->getEncodingValue(CurrentSubReg); + for (const MCPhysReg &SubReg : MCRegInfo->subregs_inclusive(Reg)) { + unsigned EncVal = MCRegInfo->getEncodingValue(SubReg); Value |= 1 << EncVal; - if (GPR32RegClass->contains(CurrentSubReg) || - GPR64RegClass->contains(CurrentSubReg)) + if (GPR32RegClass->contains(SubReg) || GPR64RegClass->contains(SubReg)) ri_gprmask |= Value; - else if (COP0RegClass->contains(CurrentSubReg)) + else if (COP0RegClass->contains(SubReg)) ri_cprmask[0] |= Value; // MIPS COP1 is the FPU. - else if (FGR32RegClass->contains(CurrentSubReg) || - FGR64RegClass->contains(CurrentSubReg) || - AFGR64RegClass->contains(CurrentSubReg) || - MSA128BRegClass->contains(CurrentSubReg)) + else if (FGR32RegClass->contains(SubReg) || + FGR64RegClass->contains(SubReg) || + AFGR64RegClass->contains(SubReg) || + MSA128BRegClass->contains(SubReg)) ri_cprmask[1] |= Value; - else if (COP2RegClass->contains(CurrentSubReg)) + else if (COP2RegClass->contains(SubReg)) ri_cprmask[2] |= Value; - else if (COP3RegClass->contains(CurrentSubReg)) + else if (COP3RegClass->contains(SubReg)) ri_cprmask[3] |= Value; } } diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -530,23 +530,20 @@ Reserved.set(X86::MXCSR); // Set the stack-pointer register and its aliases as reserved. - for (MCSubRegIterator I(X86::RSP, this, /*IncludeSelf=*/true); I.isValid(); - ++I) - Reserved.set(*I); + for (const MCPhysReg &SubReg : subregs_inclusive(X86::RSP)) + Reserved.set(SubReg); // Set the Shadow Stack Pointer as reserved. Reserved.set(X86::SSP); // Set the instruction pointer register and its aliases as reserved. - for (MCSubRegIterator I(X86::RIP, this, /*IncludeSelf=*/true); I.isValid(); - ++I) - Reserved.set(*I); + for (const MCPhysReg &SubReg : subregs_inclusive(X86::RIP)) + Reserved.set(SubReg); // Set the frame-pointer register and its aliases as reserved if needed. if (TFI->hasFP(MF)) { - for (MCSubRegIterator I(X86::RBP, this, /*IncludeSelf=*/true); I.isValid(); - ++I) - Reserved.set(*I); + for (const MCPhysReg &SubReg : subregs_inclusive(X86::RBP)) + Reserved.set(SubReg); } // Set the base-pointer register and its aliases as reserved if needed. @@ -559,9 +556,8 @@ "this calling convention."); Register BasePtr = getX86SubSuperRegister(getBaseRegister(), 64); - for (MCSubRegIterator I(BasePtr, this, /*IncludeSelf=*/true); - I.isValid(); ++I) - Reserved.set(*I); + for (const MCPhysReg &SubReg : subregs_inclusive(BasePtr)) + Reserved.set(SubReg); } // Mark the segment registers as reserved.