1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceRegAlloc.h - Linear-scan reg. allocation --*- C++ -*-===// 2*03ce13f7SAndroid Build Coastguard Worker // 3*03ce13f7SAndroid Build Coastguard Worker // The Subzero Code Generator 4*03ce13f7SAndroid Build Coastguard Worker // 5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*03ce13f7SAndroid Build Coastguard Worker // 8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*03ce13f7SAndroid Build Coastguard Worker /// 10*03ce13f7SAndroid Build Coastguard Worker /// \file 11*03ce13f7SAndroid Build Coastguard Worker /// \brief Declares the LinearScan data structure used during linear-scan 12*03ce13f7SAndroid Build Coastguard Worker /// register allocation. 13*03ce13f7SAndroid Build Coastguard Worker /// 14*03ce13f7SAndroid Build Coastguard Worker /// This holds the various work queues for the linear-scan algorithm. 15*03ce13f7SAndroid Build Coastguard Worker /// 16*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 17*03ce13f7SAndroid Build Coastguard Worker 18*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICEREGALLOC_H 19*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICEREGALLOC_H 20*03ce13f7SAndroid Build Coastguard Worker 21*03ce13f7SAndroid Build Coastguard Worker #include "IceBitVector.h" 22*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h" 23*03ce13f7SAndroid Build Coastguard Worker #include "IceOperand.h" 24*03ce13f7SAndroid Build Coastguard Worker #include "IceTypes.h" 25*03ce13f7SAndroid Build Coastguard Worker 26*03ce13f7SAndroid Build Coastguard Worker namespace Ice { 27*03ce13f7SAndroid Build Coastguard Worker 28*03ce13f7SAndroid Build Coastguard Worker class LinearScan { 29*03ce13f7SAndroid Build Coastguard Worker LinearScan() = delete; 30*03ce13f7SAndroid Build Coastguard Worker LinearScan(const LinearScan &) = delete; 31*03ce13f7SAndroid Build Coastguard Worker LinearScan &operator=(const LinearScan &) = delete; 32*03ce13f7SAndroid Build Coastguard Worker 33*03ce13f7SAndroid Build Coastguard Worker public: 34*03ce13f7SAndroid Build Coastguard Worker explicit LinearScan(Cfg *Func); 35*03ce13f7SAndroid Build Coastguard Worker void init(RegAllocKind Kind, CfgSet<Variable *> ExcludeVars); 36*03ce13f7SAndroid Build Coastguard Worker void scan(const SmallBitVector &RegMask); 37*03ce13f7SAndroid Build Coastguard Worker // Returns the number of times some variable has been assigned a register but 38*03ce13f7SAndroid Build Coastguard Worker // later evicted because of a higher-priority allocation. The idea is that we 39*03ce13f7SAndroid Build Coastguard Worker // can implement "second-chance bin-packing" by rerunning register allocation 40*03ce13f7SAndroid Build Coastguard Worker // until there are no more evictions. getNumEvictions()41*03ce13f7SAndroid Build Coastguard Worker SizeT getNumEvictions() const { return Evicted.size(); } hasEvictions()42*03ce13f7SAndroid Build Coastguard Worker bool hasEvictions() const { return !Evicted.empty(); } 43*03ce13f7SAndroid Build Coastguard Worker void dump(Cfg *Func) const; 44*03ce13f7SAndroid Build Coastguard Worker 45*03ce13f7SAndroid Build Coastguard Worker // TODO(stichnot): Statically choose the size based on the target being 46*03ce13f7SAndroid Build Coastguard Worker // compiled. For now, choose a value large enough to fit into the 47*03ce13f7SAndroid Build Coastguard Worker // SmallVector's fixed portion, which is 32 for x86-32, 84 for x86-64, and 102 48*03ce13f7SAndroid Build Coastguard Worker // for ARM32. 49*03ce13f7SAndroid Build Coastguard Worker static constexpr size_t REGS_SIZE = 128; 50*03ce13f7SAndroid Build Coastguard Worker 51*03ce13f7SAndroid Build Coastguard Worker private: 52*03ce13f7SAndroid Build Coastguard Worker using OrderedRanges = CfgVector<Variable *>; 53*03ce13f7SAndroid Build Coastguard Worker using UnorderedRanges = CfgVector<Variable *>; 54*03ce13f7SAndroid Build Coastguard Worker using DefUseErrorList = llvm::SmallVector<SizeT, 10>; 55*03ce13f7SAndroid Build Coastguard Worker 56*03ce13f7SAndroid Build Coastguard Worker class IterationState { 57*03ce13f7SAndroid Build Coastguard Worker IterationState(const IterationState &) = delete; 58*03ce13f7SAndroid Build Coastguard Worker IterationState operator=(const IterationState &) = delete; 59*03ce13f7SAndroid Build Coastguard Worker 60*03ce13f7SAndroid Build Coastguard Worker public: 61*03ce13f7SAndroid Build Coastguard Worker IterationState() = default; 62*03ce13f7SAndroid Build Coastguard Worker Variable *Cur = nullptr; 63*03ce13f7SAndroid Build Coastguard Worker Variable *Prefer = nullptr; 64*03ce13f7SAndroid Build Coastguard Worker RegNumT PreferReg; 65*03ce13f7SAndroid Build Coastguard Worker bool AllowOverlap = false; 66*03ce13f7SAndroid Build Coastguard Worker SmallBitVector RegMask; 67*03ce13f7SAndroid Build Coastguard Worker SmallBitVector RegMaskUnfiltered; 68*03ce13f7SAndroid Build Coastguard Worker SmallBitVector Free; 69*03ce13f7SAndroid Build Coastguard Worker SmallBitVector FreeUnfiltered; 70*03ce13f7SAndroid Build Coastguard Worker SmallBitVector PrecoloredUnhandledMask; // Note: only used for dumping 71*03ce13f7SAndroid Build Coastguard Worker llvm::SmallVector<RegWeight, REGS_SIZE> Weights; 72*03ce13f7SAndroid Build Coastguard Worker }; 73*03ce13f7SAndroid Build Coastguard Worker 74*03ce13f7SAndroid Build Coastguard Worker bool livenessValidateIntervals(const DefUseErrorList &DefsWithoutUses, 75*03ce13f7SAndroid Build Coastguard Worker const DefUseErrorList &UsesBeforeDefs, 76*03ce13f7SAndroid Build Coastguard Worker const CfgVector<InstNumberT> &LRBegin, 77*03ce13f7SAndroid Build Coastguard Worker const CfgVector<InstNumberT> &LREnd) const; 78*03ce13f7SAndroid Build Coastguard Worker void initForGlobal(); 79*03ce13f7SAndroid Build Coastguard Worker void initForInfOnly(); 80*03ce13f7SAndroid Build Coastguard Worker void initForSecondChance(); 81*03ce13f7SAndroid Build Coastguard Worker /// Move an item from the From set to the To set. From[Index] is pushed onto 82*03ce13f7SAndroid Build Coastguard Worker /// the end of To[], then the item is efficiently removed from From[] by 83*03ce13f7SAndroid Build Coastguard Worker /// effectively swapping it with the last item in From[] and then popping it 84*03ce13f7SAndroid Build Coastguard Worker /// from the back. As such, the caller is best off iterating over From[] in 85*03ce13f7SAndroid Build Coastguard Worker /// reverse order to avoid the need for special handling of the iterator. moveItem(UnorderedRanges & From,SizeT Index,UnorderedRanges & To)86*03ce13f7SAndroid Build Coastguard Worker void moveItem(UnorderedRanges &From, SizeT Index, UnorderedRanges &To) { 87*03ce13f7SAndroid Build Coastguard Worker To.push_back(From[Index]); 88*03ce13f7SAndroid Build Coastguard Worker From[Index] = From.back(); 89*03ce13f7SAndroid Build Coastguard Worker From.pop_back(); 90*03ce13f7SAndroid Build Coastguard Worker } 91*03ce13f7SAndroid Build Coastguard Worker 92*03ce13f7SAndroid Build Coastguard Worker /// \name scan helper functions. 93*03ce13f7SAndroid Build Coastguard Worker /// @{ 94*03ce13f7SAndroid Build Coastguard Worker /// Free up a register for infinite-weight Cur by spilling and reloading some 95*03ce13f7SAndroid Build Coastguard Worker /// register that isn't used during Cur's live range. 96*03ce13f7SAndroid Build Coastguard Worker void addSpillFill(IterationState &Iter); 97*03ce13f7SAndroid Build Coastguard Worker /// Check for active ranges that have expired or become inactive. 98*03ce13f7SAndroid Build Coastguard Worker void handleActiveRangeExpiredOrInactive(const Variable *Cur); 99*03ce13f7SAndroid Build Coastguard Worker /// Check for inactive ranges that have expired or reactivated. 100*03ce13f7SAndroid Build Coastguard Worker void handleInactiveRangeExpiredOrReactivated(const Variable *Cur); 101*03ce13f7SAndroid Build Coastguard Worker void findRegisterPreference(IterationState &Iter); 102*03ce13f7SAndroid Build Coastguard Worker void filterFreeWithInactiveRanges(IterationState &Iter); 103*03ce13f7SAndroid Build Coastguard Worker void filterFreeWithPrecoloredRanges(IterationState &Iter); 104*03ce13f7SAndroid Build Coastguard Worker void allocatePrecoloredRegister(Variable *Cur); 105*03ce13f7SAndroid Build Coastguard Worker void allocatePreferredRegister(IterationState &Iter); 106*03ce13f7SAndroid Build Coastguard Worker void allocateFreeRegister(IterationState &Iter, bool Filtered); 107*03ce13f7SAndroid Build Coastguard Worker void handleNoFreeRegisters(IterationState &Iter); 108*03ce13f7SAndroid Build Coastguard Worker void assignFinalRegisters(const SmallBitVector &RegMaskFull); 109*03ce13f7SAndroid Build Coastguard Worker /// @} 110*03ce13f7SAndroid Build Coastguard Worker 111*03ce13f7SAndroid Build Coastguard Worker void dumpLiveRangeTrace(const char *Label, const Variable *Item); 112*03ce13f7SAndroid Build Coastguard Worker 113*03ce13f7SAndroid Build Coastguard Worker Cfg *const Func; 114*03ce13f7SAndroid Build Coastguard Worker GlobalContext *const Ctx; 115*03ce13f7SAndroid Build Coastguard Worker TargetLowering *const Target; 116*03ce13f7SAndroid Build Coastguard Worker 117*03ce13f7SAndroid Build Coastguard Worker OrderedRanges Unhandled; 118*03ce13f7SAndroid Build Coastguard Worker /// UnhandledPrecolored is a subset of Unhandled, specially collected for 119*03ce13f7SAndroid Build Coastguard Worker /// faster processing. 120*03ce13f7SAndroid Build Coastguard Worker OrderedRanges UnhandledPrecolored; 121*03ce13f7SAndroid Build Coastguard Worker UnorderedRanges Active, Inactive, Handled; 122*03ce13f7SAndroid Build Coastguard Worker UnorderedRanges Evicted; 123*03ce13f7SAndroid Build Coastguard Worker CfgVector<InstNumberT> Kills; 124*03ce13f7SAndroid Build Coastguard Worker RegAllocKind Kind = RAK_Unknown; 125*03ce13f7SAndroid Build Coastguard Worker /// RegUses[I] is the number of live ranges (variables) that register I is 126*03ce13f7SAndroid Build Coastguard Worker /// currently assigned to. It can be greater than 1 as a result of 127*03ce13f7SAndroid Build Coastguard Worker /// AllowOverlap inference. 128*03ce13f7SAndroid Build Coastguard Worker llvm::SmallVector<int32_t, REGS_SIZE> RegUses; 129*03ce13f7SAndroid Build Coastguard Worker llvm::SmallVector<const SmallBitVector *, REGS_SIZE> RegAliases; 130*03ce13f7SAndroid Build Coastguard Worker bool FindPreference = false; 131*03ce13f7SAndroid Build Coastguard Worker bool FindOverlap = false; 132*03ce13f7SAndroid Build Coastguard Worker const bool Verbose; 133*03ce13f7SAndroid Build Coastguard Worker const bool UseReserve; 134*03ce13f7SAndroid Build Coastguard Worker CfgVector<Variable *> Vars; 135*03ce13f7SAndroid Build Coastguard Worker }; 136*03ce13f7SAndroid Build Coastguard Worker 137*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice 138*03ce13f7SAndroid Build Coastguard Worker 139*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICEREGALLOC_H 140