10c67e01eSJakob Stoklund Olesen //===-- llvm/CodeGen/AllocationOrder.h - Allocation Order -*- C++ -*-------===// 20c67e01eSJakob Stoklund Olesen // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60c67e01eSJakob Stoklund Olesen // 70c67e01eSJakob Stoklund Olesen //===----------------------------------------------------------------------===// 80c67e01eSJakob Stoklund Olesen // 90c67e01eSJakob Stoklund Olesen // This file implements an allocation order for virtual registers. 100c67e01eSJakob Stoklund Olesen // 110c67e01eSJakob Stoklund Olesen // The preferred allocation order for a virtual register depends on allocation 120c67e01eSJakob Stoklund Olesen // hints and target hooks. The AllocationOrder class encapsulates all of that. 130c67e01eSJakob Stoklund Olesen // 140c67e01eSJakob Stoklund Olesen //===----------------------------------------------------------------------===// 150c67e01eSJakob Stoklund Olesen 16a7c40ef0SBenjamin Kramer #ifndef LLVM_LIB_CODEGEN_ALLOCATIONORDER_H 17a7c40ef0SBenjamin Kramer #define LLVM_LIB_CODEGEN_ALLOCATIONORDER_H 180c67e01eSJakob Stoklund Olesen 19c784a1f9SJakob Stoklund Olesen #include "llvm/ADT/ArrayRef.h" 200d955d0bSDavid Majnemer #include "llvm/ADT/STLExtras.h" 21b268e24dSMircea Trofin #include "llvm/ADT/SmallVector.h" 22*819044adSMircea Trofin #include "llvm/CodeGen/Register.h" 23bdb55e0cSJakob Stoklund Olesen 240c67e01eSJakob Stoklund Olesen namespace llvm { 250c67e01eSJakob Stoklund Olesen 26b8bf3c0fSJakob Stoklund Olesen class RegisterClassInfo; 270c67e01eSJakob Stoklund Olesen class VirtRegMap; 285d1f12d1SMatthias Braun class LiveRegMatrix; 290c67e01eSJakob Stoklund Olesen 30f4c20253SBenjamin Kramer class LLVM_LIBRARY_VISIBILITY AllocationOrder { 316d193ba3SMircea Trofin const SmallVector<MCPhysReg, 16> Hints; 32c784a1f9SJakob Stoklund Olesen ArrayRef<MCPhysReg> Order; 33b268e24dSMircea Trofin // How far into the Order we can iterate. This is 0 if the AllocationOrder is 34b268e24dSMircea Trofin // constructed with HardHints = true, Order.size() otherwise. While 35b268e24dSMircea Trofin // technically a size_t, it will participate in comparisons with the 36b268e24dSMircea Trofin // Iterator's Pos, which must be signed, so it's typed here as signed, too, to 37b268e24dSMircea Trofin // avoid warnings and under the assumption that the size of Order is 38b268e24dSMircea Trofin // relatively small. 39b268e24dSMircea Trofin // IterationLimit defines an invalid iterator position. 40b268e24dSMircea Trofin const int IterationLimit; 414b017e68SJonas Paulsson 42c784a1f9SJakob Stoklund Olesen public: 43b268e24dSMircea Trofin /// Forward iterator for an AllocationOrder. 44b268e24dSMircea Trofin class Iterator final { 45b268e24dSMircea Trofin const AllocationOrder &AO; 46b268e24dSMircea Trofin int Pos = 0; 47b268e24dSMircea Trofin 48b268e24dSMircea Trofin public: Iterator(const AllocationOrder & AO,int Pos)49b268e24dSMircea Trofin Iterator(const AllocationOrder &AO, int Pos) : AO(AO), Pos(Pos) {} 50b268e24dSMircea Trofin 51b268e24dSMircea Trofin /// Return true if the curent position is that of a preferred register. isHint()52b268e24dSMircea Trofin bool isHint() const { return Pos < 0; } 53b268e24dSMircea Trofin 54b268e24dSMircea Trofin /// Return the next physical register in the allocation order. 55b268e24dSMircea Trofin MCRegister operator*() const { 56b268e24dSMircea Trofin if (Pos < 0) 57b268e24dSMircea Trofin return AO.Hints.end()[Pos]; 58b268e24dSMircea Trofin assert(Pos < AO.IterationLimit); 59b268e24dSMircea Trofin return AO.Order[Pos]; 60b268e24dSMircea Trofin } 61b268e24dSMircea Trofin 62b268e24dSMircea Trofin /// Advance the iterator to the next position. If that's past the Hints 63b268e24dSMircea Trofin /// list, advance to the first value that's not also in the Hints list. 64b268e24dSMircea Trofin Iterator &operator++() { 65b268e24dSMircea Trofin if (Pos < AO.IterationLimit) 66b268e24dSMircea Trofin ++Pos; 67b268e24dSMircea Trofin while (Pos >= 0 && Pos < AO.IterationLimit && AO.isHint(AO.Order[Pos])) 68b268e24dSMircea Trofin ++Pos; 69b268e24dSMircea Trofin return *this; 70b268e24dSMircea Trofin } 71b268e24dSMircea Trofin 72b268e24dSMircea Trofin bool operator==(const Iterator &Other) const { 73b268e24dSMircea Trofin assert(&AO == &Other.AO); 74b268e24dSMircea Trofin return Pos == Other.Pos; 75b268e24dSMircea Trofin } 76b268e24dSMircea Trofin 77b268e24dSMircea Trofin bool operator!=(const Iterator &Other) const { return !(*this == Other); } 78b268e24dSMircea Trofin }; 794b017e68SJonas Paulsson 80c784a1f9SJakob Stoklund Olesen /// Create a new AllocationOrder for VirtReg. 810c67e01eSJakob Stoklund Olesen /// @param VirtReg Virtual register to allocate for. 820c67e01eSJakob Stoklund Olesen /// @param VRM Virtual register map for function. 835b9deabaSJakob Stoklund Olesen /// @param RegClassInfo Information about reserved and allocatable registers. 846d193ba3SMircea Trofin static AllocationOrder create(unsigned VirtReg, const VirtRegMap &VRM, 855d1f12d1SMatthias Braun const RegisterClassInfo &RegClassInfo, 865d1f12d1SMatthias Braun const LiveRegMatrix *Matrix); 870c67e01eSJakob Stoklund Olesen 886d193ba3SMircea Trofin /// Create an AllocationOrder given the Hits, Order, and HardHits values. 896d193ba3SMircea Trofin /// Use the create method above - the ctor is for unittests. AllocationOrder(SmallVector<MCPhysReg,16> && Hints,ArrayRef<MCPhysReg> Order,bool HardHints)906d193ba3SMircea Trofin AllocationOrder(SmallVector<MCPhysReg, 16> &&Hints, ArrayRef<MCPhysReg> Order, 916d193ba3SMircea Trofin bool HardHints) 926d193ba3SMircea Trofin : Hints(std::move(Hints)), Order(Order), 93b268e24dSMircea Trofin IterationLimit(HardHints ? 0 : static_cast<int>(Order.size())) {} 94b268e24dSMircea Trofin begin()95b268e24dSMircea Trofin Iterator begin() const { 96b268e24dSMircea Trofin return Iterator(*this, -(static_cast<int>(Hints.size()))); 97b268e24dSMircea Trofin } 98b268e24dSMircea Trofin end()99b268e24dSMircea Trofin Iterator end() const { return Iterator(*this, IterationLimit); } 100b268e24dSMircea Trofin getOrderLimitEnd(unsigned OrderLimit)101b268e24dSMircea Trofin Iterator getOrderLimitEnd(unsigned OrderLimit) const { 102b268e24dSMircea Trofin assert(OrderLimit <= Order.size()); 103b268e24dSMircea Trofin if (OrderLimit == 0) 104b268e24dSMircea Trofin return end(); 105b268e24dSMircea Trofin Iterator Ret(*this, 106b268e24dSMircea Trofin std::min(static_cast<int>(OrderLimit) - 1, IterationLimit)); 107b268e24dSMircea Trofin return ++Ret; 108b268e24dSMircea Trofin } 1096d193ba3SMircea Trofin 1103dd236cdSJakob Stoklund Olesen /// Get the allocation order without reordered hints. getOrder()1113dd236cdSJakob Stoklund Olesen ArrayRef<MCPhysReg> getOrder() const { return Order; } 1123dd236cdSJakob Stoklund Olesen 113*819044adSMircea Trofin /// Return true if Reg is a preferred physical register. isHint(Register Reg)114*819044adSMircea Trofin bool isHint(Register Reg) const { 115*819044adSMircea Trofin assert(!Reg.isPhysical() || 116*819044adSMircea Trofin Reg.id() < 117*819044adSMircea Trofin static_cast<uint32_t>(std::numeric_limits<MCPhysReg>::max())); 118*819044adSMircea Trofin return Reg.isPhysical() && is_contained(Hints, Reg.id()); 119*819044adSMircea Trofin } 1200c67e01eSJakob Stoklund Olesen }; 1210c67e01eSJakob Stoklund Olesen 1220c67e01eSJakob Stoklund Olesen } // end namespace llvm 1230c67e01eSJakob Stoklund Olesen 1240c67e01eSJakob Stoklund Olesen #endif 125