diff --git a/llvm/lib/CodeGen/AllocationOrder.h b/llvm/lib/CodeGen/AllocationOrder.h --- a/llvm/lib/CodeGen/AllocationOrder.h +++ b/llvm/lib/CodeGen/AllocationOrder.h @@ -17,8 +17,8 @@ #define LLVM_LIB_CODEGEN_ALLOCATIONORDER_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCRegister.h" namespace llvm { @@ -30,12 +30,37 @@ class LLVM_LIBRARY_VISIBILITY AllocationOrder { SmallVector Hints; ArrayRef Order; - int Pos; - // If HardHints is true, *only* Hints will be returned. - bool HardHints; + bool HardHints = false; public: + class Iterator final { + const ArrayRef Hints; + const ArrayRef Order; + int Pos = 0; + + public: + Iterator(ArrayRef Hints, ArrayRef Order) + : Hints(Hints), Order(Order), Pos(-static_cast(Hints.size())) {} + + /// Return true if the last register returned from next() was a preferred + /// register. + bool isHint() const { return Pos <= 0; } + + /// Return the next physical register in the allocation order, or 0. + /// It is safe to call next() again after it returned 0, it will keep + /// returning 0. + MCPhysReg next() { + if (Pos < 0) + return Hints.end()[Pos++]; + while (Pos < static_cast(Order.size())) { + unsigned Reg = Order[Pos++]; + if (!is_contained(Hints, Reg)) + return Reg; + } + return 0; + } + }; /// Create a new AllocationOrder for VirtReg. /// @param VirtReg Virtual register to allocate for. @@ -46,32 +71,20 @@ const RegisterClassInfo &RegClassInfo, const LiveRegMatrix *Matrix); - /// Get the allocation order without reordered hints. - ArrayRef getOrder() const { return Order; } - - /// Return the next physical register in the allocation order, or 0. - /// It is safe to call next() again after it returned 0, it will keep - /// returning 0 until rewind() is called. - unsigned next(unsigned Limit = 0) { - if (Pos < 0) - return Hints.end()[Pos++]; - if (HardHints) - return 0; - if (!Limit) + Iterator getIterator(unsigned Limit = 0) const { + // If Limit is unspecified, we use the whole Order set. + if (Limit == 0) Limit = Order.size(); - while (Pos < int(Limit)) { - unsigned Reg = Order[Pos++]; - if (!isHint(Reg)) - return Reg; - } - return 0; + // If HardHints, we disregard the Order set completely - regardless of + // Limit's value. + if (HardHints) + Limit = 0; + // Expose to the iterator the subset of Order of up to Limit elements. + return Iterator(Hints, ArrayRef(Order.data(), Limit)); } - /// Start over from the beginning. - void rewind() { Pos = -int(Hints.size()); } - - /// Return true if the last register returned from next() was a preferred register. - bool isHint() const { return Pos <= 0; } + /// Get the allocation order without reordered hints. + ArrayRef getOrder() const { return Order; } /// Return true if PhysReg is a preferred register. bool isHint(unsigned PhysReg) const { return is_contained(Hints, PhysReg); } diff --git a/llvm/lib/CodeGen/AllocationOrder.cpp b/llvm/lib/CodeGen/AllocationOrder.cpp --- a/llvm/lib/CodeGen/AllocationOrder.cpp +++ b/llvm/lib/CodeGen/AllocationOrder.cpp @@ -26,17 +26,14 @@ #define DEBUG_TYPE "regalloc" // Compare VirtRegMap::getRegAllocPref(). -AllocationOrder::AllocationOrder(unsigned VirtReg, - const VirtRegMap &VRM, +AllocationOrder::AllocationOrder(unsigned VirtReg, const VirtRegMap &VRM, const RegisterClassInfo &RegClassInfo, - const LiveRegMatrix *Matrix) - : Pos(0), HardHints(false) { + const LiveRegMatrix *Matrix) { const MachineFunction &MF = VRM.getMachineFunction(); const TargetRegisterInfo *TRI = &VRM.getTargetRegInfo(); Order = RegClassInfo.getOrder(MF.getRegInfo().getRegClass(VirtReg)); if (TRI->getRegAllocationHints(VirtReg, Order, Hints, MF, &VRM, Matrix)) HardHints = true; - rewind(); LLVM_DEBUG({ if (!Hints.empty()) { diff --git a/llvm/lib/CodeGen/RegAllocBasic.cpp b/llvm/lib/CodeGen/RegAllocBasic.cpp --- a/llvm/lib/CodeGen/RegAllocBasic.cpp +++ b/llvm/lib/CodeGen/RegAllocBasic.cpp @@ -260,7 +260,8 @@ // Check for an available register in this class. AllocationOrder Order(VirtReg.reg(), *VRM, RegClassInfo, Matrix); - while (Register PhysReg = Order.next()) { + auto It = Order.getIterator(); + while (Register PhysReg = It.next()) { // Check for interference in PhysReg switch (Matrix->checkInterference(VirtReg, PhysReg)) { case LiveRegMatrix::IK_Free: diff --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp --- a/llvm/lib/CodeGen/RegAllocGreedy.cpp +++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp @@ -756,12 +756,12 @@ AllocationOrder &Order, SmallVectorImpl &NewVRegs, const SmallVirtRegSet &FixedRegisters) { - Order.rewind(); + auto It = Order.getIterator(); Register PhysReg; - while ((PhysReg = Order.next())) + while ((PhysReg = It.next())) if (!Matrix->checkInterference(VirtReg, PhysReg)) break; - if (!PhysReg || Order.isHint()) + if (!PhysReg || It.isHint()) return PhysReg; // PhysReg is available, but there may be a better choice. @@ -802,7 +802,8 @@ Register RAGreedy::canReassign(LiveInterval &VirtReg, Register PrevReg) { AllocationOrder Order(VirtReg.reg(), *VRM, RegClassInfo, Matrix); Register PhysReg; - while ((PhysReg = Order.next())) { + auto It = Order.getIterator(); + while ((PhysReg = It.next())) { if (PhysReg == PrevReg) continue; @@ -1132,8 +1133,8 @@ } } - Order.rewind(); - while (MCRegister PhysReg = Order.next(OrderLimit)) { + auto I = Order.getIterator(OrderLimit); + while (MCRegister PhysReg = I.next()) { if (TRI->getCostPerUse(PhysReg) >= CostPerUseLimit) continue; // The first use of a callee-saved register in a function has cost 1. @@ -1154,7 +1155,7 @@ BestPhys = PhysReg; // Stop if the hint can be used. - if (Order.isHint()) + if (I.isHint()) break; } @@ -1849,8 +1850,8 @@ unsigned &NumCands, bool IgnoreCSR, bool *CanCauseEvictionChain) { unsigned BestCand = NoCand; - Order.rewind(); - while (unsigned PhysReg = Order.next()) { + auto I = Order.getIterator(); + while (auto PhysReg = I.next()) { if (IgnoreCSR && isUnusedCalleeSavedReg(PhysReg)) continue; @@ -2288,8 +2289,8 @@ (1.0f / MBFI->getEntryFreq()); SmallVector GapWeight; - Order.rewind(); - while (unsigned PhysReg = Order.next()) { + auto I = Order.getIterator(); + while (unsigned PhysReg = I.next()) { // Keep track of the largest spill weight that would need to be evicted in // order to make use of PhysReg between UseSlots[I] and UseSlots[I + 1]. calcGapWeights(PhysReg, GapWeight); @@ -2606,8 +2607,8 @@ FixedRegisters.insert(VirtReg.reg()); SmallVector CurrentNewVRegs; - Order.rewind(); - while (Register PhysReg = Order.next()) { + auto It = Order.getIterator(); + while (Register PhysReg = It.next()) { LLVM_DEBUG(dbgs() << "Try to assign: " << VirtReg << " to " << printReg(PhysReg, TRI) << '\n'); RecoloringCandidates.clear();