10b57cec5SDimitry Andric //===-- llvm/CodeGen/AllocationOrder.h - Allocation Order -*- C++ -*-------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements an allocation order for virtual registers. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric // The preferred allocation order for a virtual register depends on allocation 120b57cec5SDimitry Andric // hints and target hooks. The AllocationOrder class encapsulates all of that. 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_ALLOCATIONORDER_H 170b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_ALLOCATIONORDER_H 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 200b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 21*e8d8bef9SDimitry Andric #include "llvm/ADT/SmallVector.h" 22*e8d8bef9SDimitry Andric #include "llvm/CodeGen/Register.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace llvm { 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric class RegisterClassInfo; 270b57cec5SDimitry Andric class VirtRegMap; 280b57cec5SDimitry Andric class LiveRegMatrix; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY AllocationOrder { 31*e8d8bef9SDimitry Andric const SmallVector<MCPhysReg, 16> Hints; 320b57cec5SDimitry Andric ArrayRef<MCPhysReg> Order; 33*e8d8bef9SDimitry Andric // How far into the Order we can iterate. This is 0 if the AllocationOrder is 34*e8d8bef9SDimitry Andric // constructed with HardHints = true, Order.size() otherwise. While 35*e8d8bef9SDimitry Andric // technically a size_t, it will participate in comparisons with the 36*e8d8bef9SDimitry Andric // Iterator's Pos, which must be signed, so it's typed here as signed, too, to 37*e8d8bef9SDimitry Andric // avoid warnings and under the assumption that the size of Order is 38*e8d8bef9SDimitry Andric // relatively small. 39*e8d8bef9SDimitry Andric // IterationLimit defines an invalid iterator position. 40*e8d8bef9SDimitry Andric const int IterationLimit; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric public: 43*e8d8bef9SDimitry Andric /// Forward iterator for an AllocationOrder. 44*e8d8bef9SDimitry Andric class Iterator final { 45*e8d8bef9SDimitry Andric const AllocationOrder &AO; 46*e8d8bef9SDimitry Andric int Pos = 0; 47*e8d8bef9SDimitry Andric 48*e8d8bef9SDimitry Andric public: Iterator(const AllocationOrder & AO,int Pos)49*e8d8bef9SDimitry Andric Iterator(const AllocationOrder &AO, int Pos) : AO(AO), Pos(Pos) {} 50*e8d8bef9SDimitry Andric 51*e8d8bef9SDimitry Andric /// Return true if the curent position is that of a preferred register. isHint()52*e8d8bef9SDimitry Andric bool isHint() const { return Pos < 0; } 53*e8d8bef9SDimitry Andric 54*e8d8bef9SDimitry Andric /// Return the next physical register in the allocation order. 55*e8d8bef9SDimitry Andric MCRegister operator*() const { 56*e8d8bef9SDimitry Andric if (Pos < 0) 57*e8d8bef9SDimitry Andric return AO.Hints.end()[Pos]; 58*e8d8bef9SDimitry Andric assert(Pos < AO.IterationLimit); 59*e8d8bef9SDimitry Andric return AO.Order[Pos]; 60*e8d8bef9SDimitry Andric } 61*e8d8bef9SDimitry Andric 62*e8d8bef9SDimitry Andric /// Advance the iterator to the next position. If that's past the Hints 63*e8d8bef9SDimitry Andric /// list, advance to the first value that's not also in the Hints list. 64*e8d8bef9SDimitry Andric Iterator &operator++() { 65*e8d8bef9SDimitry Andric if (Pos < AO.IterationLimit) 66*e8d8bef9SDimitry Andric ++Pos; 67*e8d8bef9SDimitry Andric while (Pos >= 0 && Pos < AO.IterationLimit && AO.isHint(AO.Order[Pos])) 68*e8d8bef9SDimitry Andric ++Pos; 69*e8d8bef9SDimitry Andric return *this; 70*e8d8bef9SDimitry Andric } 71*e8d8bef9SDimitry Andric 72*e8d8bef9SDimitry Andric bool operator==(const Iterator &Other) const { 73*e8d8bef9SDimitry Andric assert(&AO == &Other.AO); 74*e8d8bef9SDimitry Andric return Pos == Other.Pos; 75*e8d8bef9SDimitry Andric } 76*e8d8bef9SDimitry Andric 77*e8d8bef9SDimitry Andric bool operator!=(const Iterator &Other) const { return !(*this == Other); } 78*e8d8bef9SDimitry Andric }; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric /// Create a new AllocationOrder for VirtReg. 810b57cec5SDimitry Andric /// @param VirtReg Virtual register to allocate for. 820b57cec5SDimitry Andric /// @param VRM Virtual register map for function. 830b57cec5SDimitry Andric /// @param RegClassInfo Information about reserved and allocatable registers. 84*e8d8bef9SDimitry Andric static AllocationOrder create(unsigned VirtReg, const VirtRegMap &VRM, 850b57cec5SDimitry Andric const RegisterClassInfo &RegClassInfo, 860b57cec5SDimitry Andric const LiveRegMatrix *Matrix); 870b57cec5SDimitry Andric 88*e8d8bef9SDimitry Andric /// Create an AllocationOrder given the Hits, Order, and HardHits values. 89*e8d8bef9SDimitry Andric /// Use the create method above - the ctor is for unittests. AllocationOrder(SmallVector<MCPhysReg,16> && Hints,ArrayRef<MCPhysReg> Order,bool HardHints)90*e8d8bef9SDimitry Andric AllocationOrder(SmallVector<MCPhysReg, 16> &&Hints, ArrayRef<MCPhysReg> Order, 91*e8d8bef9SDimitry Andric bool HardHints) 92*e8d8bef9SDimitry Andric : Hints(std::move(Hints)), Order(Order), 93*e8d8bef9SDimitry Andric IterationLimit(HardHints ? 0 : static_cast<int>(Order.size())) {} 94*e8d8bef9SDimitry Andric begin()95*e8d8bef9SDimitry Andric Iterator begin() const { 96*e8d8bef9SDimitry Andric return Iterator(*this, -(static_cast<int>(Hints.size()))); 97*e8d8bef9SDimitry Andric } 98*e8d8bef9SDimitry Andric end()99*e8d8bef9SDimitry Andric Iterator end() const { return Iterator(*this, IterationLimit); } 100*e8d8bef9SDimitry Andric getOrderLimitEnd(unsigned OrderLimit)101*e8d8bef9SDimitry Andric Iterator getOrderLimitEnd(unsigned OrderLimit) const { 102*e8d8bef9SDimitry Andric assert(OrderLimit <= Order.size()); 103*e8d8bef9SDimitry Andric if (OrderLimit == 0) 104*e8d8bef9SDimitry Andric return end(); 105*e8d8bef9SDimitry Andric Iterator Ret(*this, 106*e8d8bef9SDimitry Andric std::min(static_cast<int>(OrderLimit) - 1, IterationLimit)); 107*e8d8bef9SDimitry Andric return ++Ret; 108*e8d8bef9SDimitry Andric } 109*e8d8bef9SDimitry Andric 1100b57cec5SDimitry Andric /// Get the allocation order without reordered hints. getOrder()1110b57cec5SDimitry Andric ArrayRef<MCPhysReg> getOrder() const { return Order; } 1120b57cec5SDimitry Andric 113*e8d8bef9SDimitry Andric /// Return true if Reg is a preferred physical register. isHint(Register Reg)114*e8d8bef9SDimitry Andric bool isHint(Register Reg) const { 115*e8d8bef9SDimitry Andric assert(!Reg.isPhysical() || 116*e8d8bef9SDimitry Andric Reg.id() < 117*e8d8bef9SDimitry Andric static_cast<uint32_t>(std::numeric_limits<MCPhysReg>::max())); 118*e8d8bef9SDimitry Andric return Reg.isPhysical() && is_contained(Hints, Reg.id()); 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric }; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric } // end namespace llvm 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric #endif 125