xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/AllocationOrder.h (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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