| //===-- llvm/CodeGen/AllocationOrder.h - Allocation Order -*- C++ -*-------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements an allocation order for virtual registers. |
| // |
| // The preferred allocation order for a virtual register depends on allocation |
| // hints and target hooks. The AllocationOrder class encapsulates all of that. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_LIB_CODEGEN_ALLOCATIONORDER_H |
| #define LLVM_LIB_CODEGEN_ALLOCATIONORDER_H |
| |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/CodeGen/Register.h" |
| |
| namespace llvm { |
| |
| class RegisterClassInfo; |
| class VirtRegMap; |
| class LiveRegMatrix; |
| |
| class LLVM_LIBRARY_VISIBILITY AllocationOrder { |
| const SmallVector<MCPhysReg, 16> Hints; |
| ArrayRef<MCPhysReg> Order; |
| // How far into the Order we can iterate. This is 0 if the AllocationOrder is |
| // constructed with HardHints = true, Order.size() otherwise. While |
| // technically a size_t, it will participate in comparisons with the |
| // Iterator's Pos, which must be signed, so it's typed here as signed, too, to |
| // avoid warnings and under the assumption that the size of Order is |
| // relatively small. |
| // IterationLimit defines an invalid iterator position. |
| const int IterationLimit; |
| |
| public: |
| /// Forward iterator for an AllocationOrder. |
| class Iterator final { |
| const AllocationOrder &AO; |
| int Pos = 0; |
| |
| public: |
| Iterator(const AllocationOrder &AO, int Pos) : AO(AO), Pos(Pos) {} |
| |
| /// Return true if the curent position is that of a preferred register. |
| bool isHint() const { return Pos < 0; } |
| |
| /// Return the next physical register in the allocation order. |
| MCRegister operator*() const { |
| if (Pos < 0) |
| return AO.Hints.end()[Pos]; |
| assert(Pos < AO.IterationLimit); |
| return AO.Order[Pos]; |
| } |
| |
| /// Advance the iterator to the next position. If that's past the Hints |
| /// list, advance to the first value that's not also in the Hints list. |
| Iterator &operator++() { |
| if (Pos < AO.IterationLimit) |
| ++Pos; |
| while (Pos >= 0 && Pos < AO.IterationLimit && AO.isHint(AO.Order[Pos])) |
| ++Pos; |
| return *this; |
| } |
| |
| bool operator==(const Iterator &Other) const { |
| assert(&AO == &Other.AO); |
| return Pos == Other.Pos; |
| } |
| |
| bool operator!=(const Iterator &Other) const { return !(*this == Other); } |
| }; |
| |
| /// Create a new AllocationOrder for VirtReg. |
| /// @param VirtReg Virtual register to allocate for. |
| /// @param VRM Virtual register map for function. |
| /// @param RegClassInfo Information about reserved and allocatable registers. |
| static AllocationOrder create(unsigned VirtReg, const VirtRegMap &VRM, |
| const RegisterClassInfo &RegClassInfo, |
| const LiveRegMatrix *Matrix); |
| |
| /// Create an AllocationOrder given the Hits, Order, and HardHits values. |
| /// Use the create method above - the ctor is for unittests. |
| AllocationOrder(SmallVector<MCPhysReg, 16> &&Hints, ArrayRef<MCPhysReg> Order, |
| bool HardHints) |
| : Hints(std::move(Hints)), Order(Order), |
| IterationLimit(HardHints ? 0 : static_cast<int>(Order.size())) {} |
| |
| Iterator begin() const { |
| return Iterator(*this, -(static_cast<int>(Hints.size()))); |
| } |
| |
| Iterator end() const { return Iterator(*this, IterationLimit); } |
| |
| Iterator getOrderLimitEnd(unsigned OrderLimit) const { |
| assert(OrderLimit <= Order.size()); |
| if (OrderLimit == 0) |
| return end(); |
| Iterator Ret(*this, |
| std::min(static_cast<int>(OrderLimit) - 1, IterationLimit)); |
| return ++Ret; |
| } |
| |
| /// Get the allocation order without reordered hints. |
| ArrayRef<MCPhysReg> getOrder() const { return Order; } |
| |
| /// Return true if Reg is a preferred physical register. |
| bool isHint(Register Reg) const { |
| assert(!Reg.isPhysical() || |
| Reg.id() < |
| static_cast<uint32_t>(std::numeric_limits<MCPhysReg>::max())); |
| return Reg.isPhysical() && is_contained(Hints, Reg.id()); |
| } |
| }; |
| |
| } // end namespace llvm |
| |
| #endif |