1*0b57cec5SDimitry Andric //===-- llvm/CodeGen/AllocationOrder.h - Allocation Order -*- C++ -*-------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file implements an allocation order for virtual registers. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric // The preferred allocation order for a virtual register depends on allocation 12*0b57cec5SDimitry Andric // hints and target hooks. The AllocationOrder class encapsulates all of that. 13*0b57cec5SDimitry Andric // 14*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_ALLOCATIONORDER_H 17*0b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_ALLOCATIONORDER_H 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 20*0b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 21*0b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andric namespace llvm { 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric class RegisterClassInfo; 26*0b57cec5SDimitry Andric class VirtRegMap; 27*0b57cec5SDimitry Andric class LiveRegMatrix; 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY AllocationOrder { 30*0b57cec5SDimitry Andric SmallVector<MCPhysReg, 16> Hints; 31*0b57cec5SDimitry Andric ArrayRef<MCPhysReg> Order; 32*0b57cec5SDimitry Andric int Pos; 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric // If HardHints is true, *only* Hints will be returned. 35*0b57cec5SDimitry Andric bool HardHints; 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric public: 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric /// Create a new AllocationOrder for VirtReg. 40*0b57cec5SDimitry Andric /// @param VirtReg Virtual register to allocate for. 41*0b57cec5SDimitry Andric /// @param VRM Virtual register map for function. 42*0b57cec5SDimitry Andric /// @param RegClassInfo Information about reserved and allocatable registers. 43*0b57cec5SDimitry Andric AllocationOrder(unsigned VirtReg, 44*0b57cec5SDimitry Andric const VirtRegMap &VRM, 45*0b57cec5SDimitry Andric const RegisterClassInfo &RegClassInfo, 46*0b57cec5SDimitry Andric const LiveRegMatrix *Matrix); 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric /// Get the allocation order without reordered hints. 49*0b57cec5SDimitry Andric ArrayRef<MCPhysReg> getOrder() const { return Order; } 50*0b57cec5SDimitry Andric 51*0b57cec5SDimitry Andric /// Return the next physical register in the allocation order, or 0. 52*0b57cec5SDimitry Andric /// It is safe to call next() again after it returned 0, it will keep 53*0b57cec5SDimitry Andric /// returning 0 until rewind() is called. 54*0b57cec5SDimitry Andric unsigned next(unsigned Limit = 0) { 55*0b57cec5SDimitry Andric if (Pos < 0) 56*0b57cec5SDimitry Andric return Hints.end()[Pos++]; 57*0b57cec5SDimitry Andric if (HardHints) 58*0b57cec5SDimitry Andric return 0; 59*0b57cec5SDimitry Andric if (!Limit) 60*0b57cec5SDimitry Andric Limit = Order.size(); 61*0b57cec5SDimitry Andric while (Pos < int(Limit)) { 62*0b57cec5SDimitry Andric unsigned Reg = Order[Pos++]; 63*0b57cec5SDimitry Andric if (!isHint(Reg)) 64*0b57cec5SDimitry Andric return Reg; 65*0b57cec5SDimitry Andric } 66*0b57cec5SDimitry Andric return 0; 67*0b57cec5SDimitry Andric } 68*0b57cec5SDimitry Andric 69*0b57cec5SDimitry Andric /// As next(), but allow duplicates to be returned, and stop before the 70*0b57cec5SDimitry Andric /// Limit'th register in the RegisterClassInfo allocation order. 71*0b57cec5SDimitry Andric /// 72*0b57cec5SDimitry Andric /// This can produce more than Limit registers if there are hints. 73*0b57cec5SDimitry Andric unsigned nextWithDups(unsigned Limit) { 74*0b57cec5SDimitry Andric if (Pos < 0) 75*0b57cec5SDimitry Andric return Hints.end()[Pos++]; 76*0b57cec5SDimitry Andric if (HardHints) 77*0b57cec5SDimitry Andric return 0; 78*0b57cec5SDimitry Andric if (Pos < int(Limit)) 79*0b57cec5SDimitry Andric return Order[Pos++]; 80*0b57cec5SDimitry Andric return 0; 81*0b57cec5SDimitry Andric } 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric /// Start over from the beginning. 84*0b57cec5SDimitry Andric void rewind() { Pos = -int(Hints.size()); } 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric /// Return true if the last register returned from next() was a preferred register. 87*0b57cec5SDimitry Andric bool isHint() const { return Pos <= 0; } 88*0b57cec5SDimitry Andric 89*0b57cec5SDimitry Andric /// Return true if PhysReg is a preferred register. 90*0b57cec5SDimitry Andric bool isHint(unsigned PhysReg) const { return is_contained(Hints, PhysReg); } 91*0b57cec5SDimitry Andric }; 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric } // end namespace llvm 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric #endif 96