1 | //===-- llvm/CodeGen/AllocationOrder.h - Allocation Order -*- C++ -*-------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements an allocation order for virtual registers. |
10 | // |
11 | // The preferred allocation order for a virtual register depends on allocation |
12 | // hints and target hooks. The AllocationOrder class encapsulates all of that. |
13 | // |
14 | //===----------------------------------------------------------------------===// |
15 | |
16 | #ifndef LLVM_LIB_CODEGEN_ALLOCATIONORDER_H |
17 | #define LLVM_LIB_CODEGEN_ALLOCATIONORDER_H |
18 | |
19 | #include "llvm/ADT/ArrayRef.h" |
20 | #include "llvm/ADT/STLExtras.h" |
21 | #include "llvm/ADT/SmallVector.h" |
22 | #include "llvm/CodeGen/Register.h" |
23 | |
24 | namespace llvm { |
25 | |
26 | class RegisterClassInfo; |
27 | class VirtRegMap; |
28 | class LiveRegMatrix; |
29 | |
30 | class LLVM_LIBRARY_VISIBILITY AllocationOrder { |
31 | const SmallVector<MCPhysReg, 16> Hints; |
32 | ArrayRef<MCPhysReg> Order; |
33 | // How far into the Order we can iterate. This is 0 if the AllocationOrder is |
34 | // constructed with HardHints = true, Order.size() otherwise. While |
35 | // technically a size_t, it will participate in comparisons with the |
36 | // Iterator's Pos, which must be signed, so it's typed here as signed, too, to |
37 | // avoid warnings and under the assumption that the size of Order is |
38 | // relatively small. |
39 | // IterationLimit defines an invalid iterator position. |
40 | const int IterationLimit; |
41 | |
42 | public: |
43 | /// Forward iterator for an AllocationOrder. |
44 | class Iterator final { |
45 | const AllocationOrder &AO; |
46 | int Pos = 0; |
47 | |
48 | public: |
49 | Iterator(const AllocationOrder &AO, int Pos) : AO(AO), Pos(Pos) {} |
50 | |
51 | /// Return true if the curent position is that of a preferred register. |
52 | bool isHint() const { return Pos < 0; } |
53 | |
54 | /// Return the next physical register in the allocation order. |
55 | MCRegister operator*() const { |
56 | if (Pos < 0) |
57 | return AO.Hints.end()[Pos]; |
58 | assert(Pos < AO.IterationLimit); |
59 | return AO.Order[Pos]; |
60 | } |
61 | |
62 | /// Advance the iterator to the next position. If that's past the Hints |
63 | /// list, advance to the first value that's not also in the Hints list. |
64 | Iterator &operator++() { |
65 | if (Pos < AO.IterationLimit) |
66 | ++Pos; |
67 | while (Pos >= 0 && Pos < AO.IterationLimit && AO.isHint(Reg: AO.Order[Pos])) |
68 | ++Pos; |
69 | return *this; |
70 | } |
71 | |
72 | bool operator==(const Iterator &Other) const { |
73 | assert(&AO == &Other.AO); |
74 | return Pos == Other.Pos; |
75 | } |
76 | |
77 | bool operator!=(const Iterator &Other) const { return !(*this == Other); } |
78 | }; |
79 | |
80 | /// Create a new AllocationOrder for VirtReg. |
81 | /// @param VirtReg Virtual register to allocate for. |
82 | /// @param VRM Virtual register map for function. |
83 | /// @param RegClassInfo Information about reserved and allocatable registers. |
84 | static AllocationOrder create(unsigned VirtReg, const VirtRegMap &VRM, |
85 | const RegisterClassInfo &RegClassInfo, |
86 | const LiveRegMatrix *Matrix); |
87 | |
88 | /// Create an AllocationOrder given the Hits, Order, and HardHits values. |
89 | /// Use the create method above - the ctor is for unittests. |
90 | AllocationOrder(SmallVector<MCPhysReg, 16> &&Hints, ArrayRef<MCPhysReg> Order, |
91 | bool HardHints) |
92 | : Hints(std::move(Hints)), Order(Order), |
93 | IterationLimit(HardHints ? 0 : static_cast<int>(Order.size())) {} |
94 | |
95 | Iterator begin() const { |
96 | return Iterator(*this, -(static_cast<int>(Hints.size()))); |
97 | } |
98 | |
99 | Iterator end() const { return Iterator(*this, IterationLimit); } |
100 | |
101 | Iterator getOrderLimitEnd(unsigned OrderLimit) const { |
102 | assert(OrderLimit <= Order.size()); |
103 | if (OrderLimit == 0) |
104 | return end(); |
105 | Iterator Ret(*this, |
106 | std::min(a: static_cast<int>(OrderLimit) - 1, b: IterationLimit)); |
107 | return ++Ret; |
108 | } |
109 | |
110 | /// Get the allocation order without reordered hints. |
111 | ArrayRef<MCPhysReg> getOrder() const { return Order; } |
112 | |
113 | /// Return true if Reg is a preferred physical register. |
114 | bool isHint(Register Reg) const { |
115 | assert(!Reg.isPhysical() || |
116 | Reg.id() < |
117 | static_cast<uint32_t>(std::numeric_limits<MCPhysReg>::max())); |
118 | return Reg.isPhysical() && is_contained(Range: Hints, Element: Reg.id()); |
119 | } |
120 | }; |
121 | |
122 | } // end namespace llvm |
123 | |
124 | #endif |
125 | |