//===- subzero/src/IceRegAlloc.h - Linear-scan reg. allocation --*- C++ -*-===// // // The Subzero Code Generator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// \file /// \brief Declares the LinearScan data structure used during linear-scan /// register allocation. /// /// This holds the various work queues for the linear-scan algorithm. /// //===----------------------------------------------------------------------===// #ifndef SUBZERO_SRC_ICEREGALLOC_H #define SUBZERO_SRC_ICEREGALLOC_H #include "IceDefs.h" #include "IceBitVector.h" #include "IceOperand.h" #include "IceTypes.h" namespace Ice { class LinearScan { LinearScan() = delete; LinearScan(const LinearScan &) = delete; LinearScan &operator=(const LinearScan &) = delete; public: explicit LinearScan(Cfg *Func); void init(RegAllocKind Kind, CfgSet ExcludeVars); void scan(const SmallBitVector &RegMask, bool Randomized); // Returns the number of times some variable has been assigned a register but // later evicted because of a higher-priority allocation. The idea is that we // can implement "second-chance bin-packing" by rerunning register allocation // until there are no more evictions. SizeT getNumEvictions() const { return Evicted.size(); } bool hasEvictions() const { return !Evicted.empty(); } void dump(Cfg *Func) const; // TODO(stichnot): Statically choose the size based on the target being // compiled. For now, choose a value large enough to fit into the // SmallVector's fixed portion, which is 32 for x86-32, 84 for x86-64, and 102 // for ARM32. static constexpr size_t REGS_SIZE = 128; private: using OrderedRanges = CfgVector; using UnorderedRanges = CfgVector; using DefUseErrorList = llvm::SmallVector; class IterationState { IterationState(const IterationState &) = delete; IterationState operator=(const IterationState &) = delete; public: IterationState() = default; Variable *Cur = nullptr; Variable *Prefer = nullptr; RegNumT PreferReg; bool AllowOverlap = false; SmallBitVector RegMask; SmallBitVector RegMaskUnfiltered; SmallBitVector Free; SmallBitVector FreeUnfiltered; SmallBitVector PrecoloredUnhandledMask; // Note: only used for dumping llvm::SmallVector Weights; }; bool livenessValidateIntervals(const DefUseErrorList &DefsWithoutUses, const DefUseErrorList &UsesBeforeDefs, const CfgVector &LRBegin, const CfgVector &LREnd) const; void initForGlobal(); void initForInfOnly(); void initForSecondChance(); /// Move an item from the From set to the To set. From[Index] is pushed onto /// the end of To[], then the item is efficiently removed from From[] by /// effectively swapping it with the last item in From[] and then popping it /// from the back. As such, the caller is best off iterating over From[] in /// reverse order to avoid the need for special handling of the iterator. void moveItem(UnorderedRanges &From, SizeT Index, UnorderedRanges &To) { To.push_back(From[Index]); From[Index] = From.back(); From.pop_back(); } /// \name scan helper functions. /// @{ /// Free up a register for infinite-weight Cur by spilling and reloading some /// register that isn't used during Cur's live range. void addSpillFill(IterationState &Iter); /// Check for active ranges that have expired or become inactive. void handleActiveRangeExpiredOrInactive(const Variable *Cur); /// Check for inactive ranges that have expired or reactivated. void handleInactiveRangeExpiredOrReactivated(const Variable *Cur); void findRegisterPreference(IterationState &Iter); void filterFreeWithInactiveRanges(IterationState &Iter); void filterFreeWithPrecoloredRanges(IterationState &Iter); void allocatePrecoloredRegister(Variable *Cur); void allocatePreferredRegister(IterationState &Iter); void allocateFreeRegister(IterationState &Iter, bool Filtered); void handleNoFreeRegisters(IterationState &Iter); void assignFinalRegisters(const SmallBitVector &RegMaskFull, const SmallBitVector &PreDefinedRegisters, bool Randomized); /// @} void dumpLiveRangeTrace(const char *Label, const Variable *Item); Cfg *const Func; GlobalContext *const Ctx; TargetLowering *const Target; OrderedRanges Unhandled; /// UnhandledPrecolored is a subset of Unhandled, specially collected for /// faster processing. OrderedRanges UnhandledPrecolored; UnorderedRanges Active, Inactive, Handled; UnorderedRanges Evicted; CfgVector Kills; RegAllocKind Kind = RAK_Unknown; /// RegUses[I] is the number of live ranges (variables) that register I is /// currently assigned to. It can be greater than 1 as a result of /// AllowOverlap inference. llvm::SmallVector RegUses; llvm::SmallVector RegAliases; bool FindPreference = false; bool FindOverlap = false; const bool Verbose; const bool UseReserve; CfgVector Vars; }; } // end of namespace Ice #endif // SUBZERO_SRC_ICEREGALLOC_H