xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/Common/CodeGenRegisters.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===- CodeGenRegisters.h - Register and RegisterClass Info -----*- C++ -*-===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric //
9*0fca6ea1SDimitry Andric // This file defines structures to encapsulate information gleaned from the
10*0fca6ea1SDimitry Andric // target register and register class definitions.
11*0fca6ea1SDimitry Andric //
12*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
13*0fca6ea1SDimitry Andric 
14*0fca6ea1SDimitry Andric #ifndef LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H
15*0fca6ea1SDimitry Andric #define LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H
16*0fca6ea1SDimitry Andric 
17*0fca6ea1SDimitry Andric #include "CodeGenHwModes.h"
18*0fca6ea1SDimitry Andric #include "InfoByHwMode.h"
19*0fca6ea1SDimitry Andric #include "llvm/ADT/ArrayRef.h"
20*0fca6ea1SDimitry Andric #include "llvm/ADT/BitVector.h"
21*0fca6ea1SDimitry Andric #include "llvm/ADT/DenseMap.h"
22*0fca6ea1SDimitry Andric #include "llvm/ADT/STLExtras.h"
23*0fca6ea1SDimitry Andric #include "llvm/ADT/SetVector.h"
24*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
25*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallVector.h"
26*0fca6ea1SDimitry Andric #include "llvm/ADT/SparseBitVector.h"
27*0fca6ea1SDimitry Andric #include "llvm/ADT/StringMap.h"
28*0fca6ea1SDimitry Andric #include "llvm/ADT/StringRef.h"
29*0fca6ea1SDimitry Andric #include "llvm/MC/LaneBitmask.h"
30*0fca6ea1SDimitry Andric #include "llvm/Support/ErrorHandling.h"
31*0fca6ea1SDimitry Andric #include "llvm/TableGen/Record.h"
32*0fca6ea1SDimitry Andric #include "llvm/TableGen/SetTheory.h"
33*0fca6ea1SDimitry Andric #include <cassert>
34*0fca6ea1SDimitry Andric #include <cstdint>
35*0fca6ea1SDimitry Andric #include <deque>
36*0fca6ea1SDimitry Andric #include <functional>
37*0fca6ea1SDimitry Andric #include <list>
38*0fca6ea1SDimitry Andric #include <map>
39*0fca6ea1SDimitry Andric #include <memory>
40*0fca6ea1SDimitry Andric #include <optional>
41*0fca6ea1SDimitry Andric #include <string>
42*0fca6ea1SDimitry Andric #include <utility>
43*0fca6ea1SDimitry Andric #include <vector>
44*0fca6ea1SDimitry Andric 
45*0fca6ea1SDimitry Andric namespace llvm {
46*0fca6ea1SDimitry Andric 
47*0fca6ea1SDimitry Andric class CodeGenRegBank;
48*0fca6ea1SDimitry Andric 
49*0fca6ea1SDimitry Andric /// Used to encode a step in a register lane mask transformation.
50*0fca6ea1SDimitry Andric /// Mask the bits specified in Mask, then rotate them Rol bits to the left
51*0fca6ea1SDimitry Andric /// assuming a wraparound at 32bits.
52*0fca6ea1SDimitry Andric struct MaskRolPair {
53*0fca6ea1SDimitry Andric   LaneBitmask Mask;
54*0fca6ea1SDimitry Andric   uint8_t RotateLeft;
55*0fca6ea1SDimitry Andric 
56*0fca6ea1SDimitry Andric   bool operator==(const MaskRolPair Other) const {
57*0fca6ea1SDimitry Andric     return Mask == Other.Mask && RotateLeft == Other.RotateLeft;
58*0fca6ea1SDimitry Andric   }
59*0fca6ea1SDimitry Andric   bool operator!=(const MaskRolPair Other) const {
60*0fca6ea1SDimitry Andric     return Mask != Other.Mask || RotateLeft != Other.RotateLeft;
61*0fca6ea1SDimitry Andric   }
62*0fca6ea1SDimitry Andric };
63*0fca6ea1SDimitry Andric 
64*0fca6ea1SDimitry Andric /// CodeGenSubRegIndex - Represents a sub-register index.
65*0fca6ea1SDimitry Andric class CodeGenSubRegIndex {
66*0fca6ea1SDimitry Andric   Record *const TheDef;
67*0fca6ea1SDimitry Andric   std::string Name;
68*0fca6ea1SDimitry Andric   std::string Namespace;
69*0fca6ea1SDimitry Andric 
70*0fca6ea1SDimitry Andric public:
71*0fca6ea1SDimitry Andric   SubRegRangeByHwMode Range;
72*0fca6ea1SDimitry Andric   const unsigned EnumValue;
73*0fca6ea1SDimitry Andric   mutable LaneBitmask LaneMask;
74*0fca6ea1SDimitry Andric   mutable SmallVector<MaskRolPair, 1> CompositionLaneMaskTransform;
75*0fca6ea1SDimitry Andric 
76*0fca6ea1SDimitry Andric   /// A list of subregister indexes concatenated resulting in this
77*0fca6ea1SDimitry Andric   /// subregister index. This is the reverse of CodeGenRegBank::ConcatIdx.
78*0fca6ea1SDimitry Andric   SmallVector<CodeGenSubRegIndex *, 4> ConcatenationOf;
79*0fca6ea1SDimitry Andric 
80*0fca6ea1SDimitry Andric   // Are all super-registers containing this SubRegIndex covered by their
81*0fca6ea1SDimitry Andric   // sub-registers?
82*0fca6ea1SDimitry Andric   bool AllSuperRegsCovered;
83*0fca6ea1SDimitry Andric   // A subregister index is "artificial" if every subregister obtained
84*0fca6ea1SDimitry Andric   // from applying this index is artificial. Artificial subregister
85*0fca6ea1SDimitry Andric   // indexes are not used to create new register classes.
86*0fca6ea1SDimitry Andric   bool Artificial;
87*0fca6ea1SDimitry Andric 
88*0fca6ea1SDimitry Andric   CodeGenSubRegIndex(Record *R, unsigned Enum, const CodeGenHwModes &CGH);
89*0fca6ea1SDimitry Andric   CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum);
90*0fca6ea1SDimitry Andric   CodeGenSubRegIndex(CodeGenSubRegIndex &) = delete;
91*0fca6ea1SDimitry Andric 
92*0fca6ea1SDimitry Andric   const std::string &getName() const { return Name; }
93*0fca6ea1SDimitry Andric   const std::string &getNamespace() const { return Namespace; }
94*0fca6ea1SDimitry Andric   std::string getQualifiedName() const;
95*0fca6ea1SDimitry Andric 
96*0fca6ea1SDimitry Andric   // Map of composite subreg indices.
97*0fca6ea1SDimitry Andric   typedef std::map<CodeGenSubRegIndex *, CodeGenSubRegIndex *,
98*0fca6ea1SDimitry Andric                    deref<std::less<>>>
99*0fca6ea1SDimitry Andric       CompMap;
100*0fca6ea1SDimitry Andric 
101*0fca6ea1SDimitry Andric   // Returns the subreg index that results from composing this with Idx.
102*0fca6ea1SDimitry Andric   // Returns NULL if this and Idx don't compose.
103*0fca6ea1SDimitry Andric   CodeGenSubRegIndex *compose(CodeGenSubRegIndex *Idx) const {
104*0fca6ea1SDimitry Andric     CompMap::const_iterator I = Composed.find(Idx);
105*0fca6ea1SDimitry Andric     return I == Composed.end() ? nullptr : I->second;
106*0fca6ea1SDimitry Andric   }
107*0fca6ea1SDimitry Andric 
108*0fca6ea1SDimitry Andric   // Add a composite subreg index: this+A = B.
109*0fca6ea1SDimitry Andric   // Return a conflicting composite, or NULL
110*0fca6ea1SDimitry Andric   CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A, CodeGenSubRegIndex *B,
111*0fca6ea1SDimitry Andric                                    const CodeGenHwModes &CGH) {
112*0fca6ea1SDimitry Andric     assert(A && B);
113*0fca6ea1SDimitry Andric     std::pair<CompMap::iterator, bool> Ins = Composed.insert(std::pair(A, B));
114*0fca6ea1SDimitry Andric 
115*0fca6ea1SDimitry Andric     // Synthetic subreg indices that aren't contiguous (for instance ARM
116*0fca6ea1SDimitry Andric     // register tuples) don't have a bit range, so it's OK to let
117*0fca6ea1SDimitry Andric     // B->Offset == -1. For the other cases, accumulate the offset and set
118*0fca6ea1SDimitry Andric     // the size here. Only do so if there is no offset yet though.
119*0fca6ea1SDimitry Andric     unsigned NumModes = CGH.getNumModeIds();
120*0fca6ea1SDimitry Andric     // Skip default mode.
121*0fca6ea1SDimitry Andric     for (unsigned M = 0; M < NumModes; ++M) {
122*0fca6ea1SDimitry Andric       // Handle DefaultMode last.
123*0fca6ea1SDimitry Andric       if (M == DefaultMode)
124*0fca6ea1SDimitry Andric         continue;
125*0fca6ea1SDimitry Andric       SubRegRange &Range = this->Range.get(M);
126*0fca6ea1SDimitry Andric       SubRegRange &ARange = A->Range.get(M);
127*0fca6ea1SDimitry Andric       SubRegRange &BRange = B->Range.get(M);
128*0fca6ea1SDimitry Andric 
129*0fca6ea1SDimitry Andric       if (Range.Offset != (uint16_t)-1 && ARange.Offset != (uint16_t)-1 &&
130*0fca6ea1SDimitry Andric           BRange.Offset == (uint16_t)-1) {
131*0fca6ea1SDimitry Andric         BRange.Offset = Range.Offset + ARange.Offset;
132*0fca6ea1SDimitry Andric         BRange.Size = ARange.Size;
133*0fca6ea1SDimitry Andric       }
134*0fca6ea1SDimitry Andric     }
135*0fca6ea1SDimitry Andric 
136*0fca6ea1SDimitry Andric     // Now handle default.
137*0fca6ea1SDimitry Andric     SubRegRange &Range = this->Range.get(DefaultMode);
138*0fca6ea1SDimitry Andric     SubRegRange &ARange = A->Range.get(DefaultMode);
139*0fca6ea1SDimitry Andric     SubRegRange &BRange = B->Range.get(DefaultMode);
140*0fca6ea1SDimitry Andric     if (Range.Offset != (uint16_t)-1 && ARange.Offset != (uint16_t)-1 &&
141*0fca6ea1SDimitry Andric         BRange.Offset == (uint16_t)-1) {
142*0fca6ea1SDimitry Andric       BRange.Offset = Range.Offset + ARange.Offset;
143*0fca6ea1SDimitry Andric       BRange.Size = ARange.Size;
144*0fca6ea1SDimitry Andric     }
145*0fca6ea1SDimitry Andric 
146*0fca6ea1SDimitry Andric     return (Ins.second || Ins.first->second == B) ? nullptr : Ins.first->second;
147*0fca6ea1SDimitry Andric   }
148*0fca6ea1SDimitry Andric 
149*0fca6ea1SDimitry Andric   // Update the composite maps of components specified in 'ComposedOf'.
150*0fca6ea1SDimitry Andric   void updateComponents(CodeGenRegBank &);
151*0fca6ea1SDimitry Andric 
152*0fca6ea1SDimitry Andric   // Return the map of composites.
153*0fca6ea1SDimitry Andric   const CompMap &getComposites() const { return Composed; }
154*0fca6ea1SDimitry Andric 
155*0fca6ea1SDimitry Andric   // Compute LaneMask from Composed. Return LaneMask.
156*0fca6ea1SDimitry Andric   LaneBitmask computeLaneMask() const;
157*0fca6ea1SDimitry Andric 
158*0fca6ea1SDimitry Andric   void setConcatenationOf(ArrayRef<CodeGenSubRegIndex *> Parts);
159*0fca6ea1SDimitry Andric 
160*0fca6ea1SDimitry Andric   /// Replaces subregister indexes in the `ConcatenationOf` list with
161*0fca6ea1SDimitry Andric   /// list of subregisters they are composed of (if any). Do this recursively.
162*0fca6ea1SDimitry Andric   void computeConcatTransitiveClosure();
163*0fca6ea1SDimitry Andric 
164*0fca6ea1SDimitry Andric   bool operator<(const CodeGenSubRegIndex &RHS) const {
165*0fca6ea1SDimitry Andric     return this->EnumValue < RHS.EnumValue;
166*0fca6ea1SDimitry Andric   }
167*0fca6ea1SDimitry Andric 
168*0fca6ea1SDimitry Andric private:
169*0fca6ea1SDimitry Andric   CompMap Composed;
170*0fca6ea1SDimitry Andric };
171*0fca6ea1SDimitry Andric 
172*0fca6ea1SDimitry Andric /// CodeGenRegister - Represents a register definition.
173*0fca6ea1SDimitry Andric class CodeGenRegister {
174*0fca6ea1SDimitry Andric public:
175*0fca6ea1SDimitry Andric   Record *TheDef;
176*0fca6ea1SDimitry Andric   unsigned EnumValue;
177*0fca6ea1SDimitry Andric   std::vector<int64_t> CostPerUse;
178*0fca6ea1SDimitry Andric   bool CoveredBySubRegs = true;
179*0fca6ea1SDimitry Andric   bool HasDisjunctSubRegs = false;
180*0fca6ea1SDimitry Andric   bool Artificial = true;
181*0fca6ea1SDimitry Andric   bool Constant = false;
182*0fca6ea1SDimitry Andric 
183*0fca6ea1SDimitry Andric   // Map SubRegIndex -> Register.
184*0fca6ea1SDimitry Andric   typedef std::map<CodeGenSubRegIndex *, CodeGenRegister *, deref<std::less<>>>
185*0fca6ea1SDimitry Andric       SubRegMap;
186*0fca6ea1SDimitry Andric 
187*0fca6ea1SDimitry Andric   CodeGenRegister(Record *R, unsigned Enum);
188*0fca6ea1SDimitry Andric 
189*0fca6ea1SDimitry Andric   StringRef getName() const;
190*0fca6ea1SDimitry Andric 
191*0fca6ea1SDimitry Andric   // Extract more information from TheDef. This is used to build an object
192*0fca6ea1SDimitry Andric   // graph after all CodeGenRegister objects have been created.
193*0fca6ea1SDimitry Andric   void buildObjectGraph(CodeGenRegBank &);
194*0fca6ea1SDimitry Andric 
195*0fca6ea1SDimitry Andric   // Lazily compute a map of all sub-registers.
196*0fca6ea1SDimitry Andric   // This includes unique entries for all sub-sub-registers.
197*0fca6ea1SDimitry Andric   const SubRegMap &computeSubRegs(CodeGenRegBank &);
198*0fca6ea1SDimitry Andric 
199*0fca6ea1SDimitry Andric   // Compute extra sub-registers by combining the existing sub-registers.
200*0fca6ea1SDimitry Andric   void computeSecondarySubRegs(CodeGenRegBank &);
201*0fca6ea1SDimitry Andric 
202*0fca6ea1SDimitry Andric   // Add this as a super-register to all sub-registers after the sub-register
203*0fca6ea1SDimitry Andric   // graph has been built.
204*0fca6ea1SDimitry Andric   void computeSuperRegs(CodeGenRegBank &);
205*0fca6ea1SDimitry Andric 
206*0fca6ea1SDimitry Andric   const SubRegMap &getSubRegs() const {
207*0fca6ea1SDimitry Andric     assert(SubRegsComplete && "Must precompute sub-registers");
208*0fca6ea1SDimitry Andric     return SubRegs;
209*0fca6ea1SDimitry Andric   }
210*0fca6ea1SDimitry Andric 
211*0fca6ea1SDimitry Andric   // Add sub-registers to OSet following a pre-order defined by the .td file.
212*0fca6ea1SDimitry Andric   void addSubRegsPreOrder(SetVector<const CodeGenRegister *> &OSet,
213*0fca6ea1SDimitry Andric                           CodeGenRegBank &) const;
214*0fca6ea1SDimitry Andric 
215*0fca6ea1SDimitry Andric   // Return the sub-register index naming Reg as a sub-register of this
216*0fca6ea1SDimitry Andric   // register. Returns NULL if Reg is not a sub-register.
217*0fca6ea1SDimitry Andric   CodeGenSubRegIndex *getSubRegIndex(const CodeGenRegister *Reg) const {
218*0fca6ea1SDimitry Andric     return SubReg2Idx.lookup(Reg);
219*0fca6ea1SDimitry Andric   }
220*0fca6ea1SDimitry Andric 
221*0fca6ea1SDimitry Andric   typedef std::vector<const CodeGenRegister *> SuperRegList;
222*0fca6ea1SDimitry Andric 
223*0fca6ea1SDimitry Andric   // Get the list of super-registers in topological order, small to large.
224*0fca6ea1SDimitry Andric   // This is valid after computeSubRegs visits all registers during RegBank
225*0fca6ea1SDimitry Andric   // construction.
226*0fca6ea1SDimitry Andric   const SuperRegList &getSuperRegs() const {
227*0fca6ea1SDimitry Andric     assert(SubRegsComplete && "Must precompute sub-registers");
228*0fca6ea1SDimitry Andric     return SuperRegs;
229*0fca6ea1SDimitry Andric   }
230*0fca6ea1SDimitry Andric 
231*0fca6ea1SDimitry Andric   // Get the list of ad hoc aliases. The graph is symmetric, so the list
232*0fca6ea1SDimitry Andric   // contains all registers in 'Aliases', and all registers that mention this
233*0fca6ea1SDimitry Andric   // register in 'Aliases'.
234*0fca6ea1SDimitry Andric   ArrayRef<CodeGenRegister *> getExplicitAliases() const {
235*0fca6ea1SDimitry Andric     return ExplicitAliases;
236*0fca6ea1SDimitry Andric   }
237*0fca6ea1SDimitry Andric 
238*0fca6ea1SDimitry Andric   // Get the topological signature of this register. This is a small integer
239*0fca6ea1SDimitry Andric   // less than RegBank.getNumTopoSigs(). Registers with the same TopoSig have
240*0fca6ea1SDimitry Andric   // identical sub-register structure. That is, they support the same set of
241*0fca6ea1SDimitry Andric   // sub-register indices mapping to the same kind of sub-registers
242*0fca6ea1SDimitry Andric   // (TopoSig-wise).
243*0fca6ea1SDimitry Andric   unsigned getTopoSig() const {
244*0fca6ea1SDimitry Andric     assert(SuperRegsComplete && "TopoSigs haven't been computed yet.");
245*0fca6ea1SDimitry Andric     return TopoSig;
246*0fca6ea1SDimitry Andric   }
247*0fca6ea1SDimitry Andric 
248*0fca6ea1SDimitry Andric   // List of register units in ascending order.
249*0fca6ea1SDimitry Andric   typedef SparseBitVector<> RegUnitList;
250*0fca6ea1SDimitry Andric   typedef SmallVector<LaneBitmask, 16> RegUnitLaneMaskList;
251*0fca6ea1SDimitry Andric 
252*0fca6ea1SDimitry Andric   // How many entries in RegUnitList are native?
253*0fca6ea1SDimitry Andric   RegUnitList NativeRegUnits;
254*0fca6ea1SDimitry Andric 
255*0fca6ea1SDimitry Andric   // Get the list of register units.
256*0fca6ea1SDimitry Andric   // This is only valid after computeSubRegs() completes.
257*0fca6ea1SDimitry Andric   const RegUnitList &getRegUnits() const { return RegUnits; }
258*0fca6ea1SDimitry Andric 
259*0fca6ea1SDimitry Andric   ArrayRef<LaneBitmask> getRegUnitLaneMasks() const {
260*0fca6ea1SDimitry Andric     return ArrayRef(RegUnitLaneMasks).slice(0, NativeRegUnits.count());
261*0fca6ea1SDimitry Andric   }
262*0fca6ea1SDimitry Andric 
263*0fca6ea1SDimitry Andric   // Get the native register units. This is a prefix of getRegUnits().
264*0fca6ea1SDimitry Andric   RegUnitList getNativeRegUnits() const { return NativeRegUnits; }
265*0fca6ea1SDimitry Andric 
266*0fca6ea1SDimitry Andric   void setRegUnitLaneMasks(const RegUnitLaneMaskList &LaneMasks) {
267*0fca6ea1SDimitry Andric     RegUnitLaneMasks = LaneMasks;
268*0fca6ea1SDimitry Andric   }
269*0fca6ea1SDimitry Andric 
270*0fca6ea1SDimitry Andric   // Inherit register units from subregisters.
271*0fca6ea1SDimitry Andric   // Return true if the RegUnits changed.
272*0fca6ea1SDimitry Andric   bool inheritRegUnits(CodeGenRegBank &RegBank);
273*0fca6ea1SDimitry Andric 
274*0fca6ea1SDimitry Andric   // Adopt a register unit for pressure tracking.
275*0fca6ea1SDimitry Andric   // A unit is adopted iff its unit number is >= NativeRegUnits.count().
276*0fca6ea1SDimitry Andric   void adoptRegUnit(unsigned RUID) { RegUnits.set(RUID); }
277*0fca6ea1SDimitry Andric 
278*0fca6ea1SDimitry Andric   // Get the sum of this register's register unit weights.
279*0fca6ea1SDimitry Andric   unsigned getWeight(const CodeGenRegBank &RegBank) const;
280*0fca6ea1SDimitry Andric 
281*0fca6ea1SDimitry Andric   // Canonically ordered set.
282*0fca6ea1SDimitry Andric   typedef std::vector<const CodeGenRegister *> Vec;
283*0fca6ea1SDimitry Andric 
284*0fca6ea1SDimitry Andric private:
285*0fca6ea1SDimitry Andric   bool SubRegsComplete;
286*0fca6ea1SDimitry Andric   bool SuperRegsComplete;
287*0fca6ea1SDimitry Andric   unsigned TopoSig;
288*0fca6ea1SDimitry Andric 
289*0fca6ea1SDimitry Andric   // The sub-registers explicit in the .td file form a tree.
290*0fca6ea1SDimitry Andric   SmallVector<CodeGenSubRegIndex *, 8> ExplicitSubRegIndices;
291*0fca6ea1SDimitry Andric   SmallVector<CodeGenRegister *, 8> ExplicitSubRegs;
292*0fca6ea1SDimitry Andric 
293*0fca6ea1SDimitry Andric   // Explicit ad hoc aliases, symmetrized to form an undirected graph.
294*0fca6ea1SDimitry Andric   SmallVector<CodeGenRegister *, 8> ExplicitAliases;
295*0fca6ea1SDimitry Andric 
296*0fca6ea1SDimitry Andric   // Super-registers where this is the first explicit sub-register.
297*0fca6ea1SDimitry Andric   SuperRegList LeadingSuperRegs;
298*0fca6ea1SDimitry Andric 
299*0fca6ea1SDimitry Andric   SubRegMap SubRegs;
300*0fca6ea1SDimitry Andric   SuperRegList SuperRegs;
301*0fca6ea1SDimitry Andric   DenseMap<const CodeGenRegister *, CodeGenSubRegIndex *> SubReg2Idx;
302*0fca6ea1SDimitry Andric   RegUnitList RegUnits;
303*0fca6ea1SDimitry Andric   RegUnitLaneMaskList RegUnitLaneMasks;
304*0fca6ea1SDimitry Andric };
305*0fca6ea1SDimitry Andric 
306*0fca6ea1SDimitry Andric inline bool operator<(const CodeGenRegister &A, const CodeGenRegister &B) {
307*0fca6ea1SDimitry Andric   return A.EnumValue < B.EnumValue;
308*0fca6ea1SDimitry Andric }
309*0fca6ea1SDimitry Andric 
310*0fca6ea1SDimitry Andric inline bool operator==(const CodeGenRegister &A, const CodeGenRegister &B) {
311*0fca6ea1SDimitry Andric   return A.EnumValue == B.EnumValue;
312*0fca6ea1SDimitry Andric }
313*0fca6ea1SDimitry Andric 
314*0fca6ea1SDimitry Andric class CodeGenRegisterClass {
315*0fca6ea1SDimitry Andric   CodeGenRegister::Vec Members;
316*0fca6ea1SDimitry Andric   // Allocation orders. Order[0] always contains all registers in Members.
317*0fca6ea1SDimitry Andric   std::vector<SmallVector<Record *, 16>> Orders;
318*0fca6ea1SDimitry Andric   // Bit mask of sub-classes including this, indexed by their EnumValue.
319*0fca6ea1SDimitry Andric   BitVector SubClasses;
320*0fca6ea1SDimitry Andric   // List of super-classes, topologocally ordered to have the larger classes
321*0fca6ea1SDimitry Andric   // first.  This is the same as sorting by EnumValue.
322*0fca6ea1SDimitry Andric   SmallVector<CodeGenRegisterClass *, 4> SuperClasses;
323*0fca6ea1SDimitry Andric   Record *TheDef;
324*0fca6ea1SDimitry Andric   std::string Name;
325*0fca6ea1SDimitry Andric 
326*0fca6ea1SDimitry Andric   // For a synthesized class, inherit missing properties from the nearest
327*0fca6ea1SDimitry Andric   // super-class.
328*0fca6ea1SDimitry Andric   void inheritProperties(CodeGenRegBank &);
329*0fca6ea1SDimitry Andric 
330*0fca6ea1SDimitry Andric   // Map SubRegIndex -> sub-class.  This is the largest sub-class where all
331*0fca6ea1SDimitry Andric   // registers have a SubRegIndex sub-register.
332*0fca6ea1SDimitry Andric   DenseMap<const CodeGenSubRegIndex *, CodeGenRegisterClass *>
333*0fca6ea1SDimitry Andric       SubClassWithSubReg;
334*0fca6ea1SDimitry Andric 
335*0fca6ea1SDimitry Andric   // Map SubRegIndex -> set of super-reg classes.  This is all register
336*0fca6ea1SDimitry Andric   // classes SuperRC such that:
337*0fca6ea1SDimitry Andric   //
338*0fca6ea1SDimitry Andric   //   R:SubRegIndex in this RC for all R in SuperRC.
339*0fca6ea1SDimitry Andric   //
340*0fca6ea1SDimitry Andric   DenseMap<const CodeGenSubRegIndex *, SmallPtrSet<CodeGenRegisterClass *, 8>>
341*0fca6ea1SDimitry Andric       SuperRegClasses;
342*0fca6ea1SDimitry Andric 
343*0fca6ea1SDimitry Andric   // Bit vector of TopoSigs for the registers in this class. This will be
344*0fca6ea1SDimitry Andric   // very sparse on regular architectures.
345*0fca6ea1SDimitry Andric   BitVector TopoSigs;
346*0fca6ea1SDimitry Andric 
347*0fca6ea1SDimitry Andric public:
348*0fca6ea1SDimitry Andric   unsigned EnumValue;
349*0fca6ea1SDimitry Andric   StringRef Namespace;
350*0fca6ea1SDimitry Andric   SmallVector<ValueTypeByHwMode, 4> VTs;
351*0fca6ea1SDimitry Andric   RegSizeInfoByHwMode RSI;
352*0fca6ea1SDimitry Andric   int CopyCost;
353*0fca6ea1SDimitry Andric   bool Allocatable;
354*0fca6ea1SDimitry Andric   StringRef AltOrderSelect;
355*0fca6ea1SDimitry Andric   uint8_t AllocationPriority;
356*0fca6ea1SDimitry Andric   bool GlobalPriority;
357*0fca6ea1SDimitry Andric   uint8_t TSFlags;
358*0fca6ea1SDimitry Andric   /// Contains the combination of the lane masks of all subregisters.
359*0fca6ea1SDimitry Andric   LaneBitmask LaneMask;
360*0fca6ea1SDimitry Andric   /// True if there are at least 2 subregisters which do not interfere.
361*0fca6ea1SDimitry Andric   bool HasDisjunctSubRegs;
362*0fca6ea1SDimitry Andric   bool CoveredBySubRegs;
363*0fca6ea1SDimitry Andric   /// A register class is artificial if all its members are artificial.
364*0fca6ea1SDimitry Andric   bool Artificial;
365*0fca6ea1SDimitry Andric   /// Generate register pressure set for this register class and any class
366*0fca6ea1SDimitry Andric   /// synthesized from it.
367*0fca6ea1SDimitry Andric   bool GeneratePressureSet;
368*0fca6ea1SDimitry Andric 
369*0fca6ea1SDimitry Andric   // Return the Record that defined this class, or NULL if the class was
370*0fca6ea1SDimitry Andric   // created by TableGen.
371*0fca6ea1SDimitry Andric   Record *getDef() const { return TheDef; }
372*0fca6ea1SDimitry Andric 
373*0fca6ea1SDimitry Andric   std::string getNamespaceQualification() const;
374*0fca6ea1SDimitry Andric   const std::string &getName() const { return Name; }
375*0fca6ea1SDimitry Andric   std::string getQualifiedName() const;
376*0fca6ea1SDimitry Andric   std::string getIdName() const;
377*0fca6ea1SDimitry Andric   std::string getQualifiedIdName() const;
378*0fca6ea1SDimitry Andric   ArrayRef<ValueTypeByHwMode> getValueTypes() const { return VTs; }
379*0fca6ea1SDimitry Andric   unsigned getNumValueTypes() const { return VTs.size(); }
380*0fca6ea1SDimitry Andric   bool hasType(const ValueTypeByHwMode &VT) const;
381*0fca6ea1SDimitry Andric 
382*0fca6ea1SDimitry Andric   const ValueTypeByHwMode &getValueTypeNum(unsigned VTNum) const {
383*0fca6ea1SDimitry Andric     if (VTNum < VTs.size())
384*0fca6ea1SDimitry Andric       return VTs[VTNum];
385*0fca6ea1SDimitry Andric     llvm_unreachable("VTNum greater than number of ValueTypes in RegClass!");
386*0fca6ea1SDimitry Andric   }
387*0fca6ea1SDimitry Andric 
388*0fca6ea1SDimitry Andric   // Return true if this class contains the register.
389*0fca6ea1SDimitry Andric   bool contains(const CodeGenRegister *) const;
390*0fca6ea1SDimitry Andric 
391*0fca6ea1SDimitry Andric   // Returns true if RC is a subclass.
392*0fca6ea1SDimitry Andric   // RC is a sub-class of this class if it is a valid replacement for any
393*0fca6ea1SDimitry Andric   // instruction operand where a register of this classis required. It must
394*0fca6ea1SDimitry Andric   // satisfy these conditions:
395*0fca6ea1SDimitry Andric   //
396*0fca6ea1SDimitry Andric   // 1. All RC registers are also in this.
397*0fca6ea1SDimitry Andric   // 2. The RC spill size must not be smaller than our spill size.
398*0fca6ea1SDimitry Andric   // 3. RC spill alignment must be compatible with ours.
399*0fca6ea1SDimitry Andric   //
400*0fca6ea1SDimitry Andric   bool hasSubClass(const CodeGenRegisterClass *RC) const {
401*0fca6ea1SDimitry Andric     return SubClasses.test(RC->EnumValue);
402*0fca6ea1SDimitry Andric   }
403*0fca6ea1SDimitry Andric 
404*0fca6ea1SDimitry Andric   // getSubClassWithSubReg - Returns the largest sub-class where all
405*0fca6ea1SDimitry Andric   // registers have a SubIdx sub-register.
406*0fca6ea1SDimitry Andric   CodeGenRegisterClass *
407*0fca6ea1SDimitry Andric   getSubClassWithSubReg(const CodeGenSubRegIndex *SubIdx) const {
408*0fca6ea1SDimitry Andric     return SubClassWithSubReg.lookup(SubIdx);
409*0fca6ea1SDimitry Andric   }
410*0fca6ea1SDimitry Andric 
411*0fca6ea1SDimitry Andric   /// Find largest subclass where all registers have SubIdx subregisters in
412*0fca6ea1SDimitry Andric   /// SubRegClass and the largest subregister class that contains those
413*0fca6ea1SDimitry Andric   /// subregisters without (as far as possible) also containing additional
414*0fca6ea1SDimitry Andric   /// registers.
415*0fca6ea1SDimitry Andric   ///
416*0fca6ea1SDimitry Andric   /// This can be used to find a suitable pair of classes for subregister
417*0fca6ea1SDimitry Andric   /// copies. \return std::pair<SubClass, SubRegClass> where SubClass is a
418*0fca6ea1SDimitry Andric   /// SubClass is a class where every register has SubIdx and SubRegClass is a
419*0fca6ea1SDimitry Andric   /// class where every register is covered by the SubIdx subregister of
420*0fca6ea1SDimitry Andric   /// SubClass.
421*0fca6ea1SDimitry Andric   std::optional<std::pair<CodeGenRegisterClass *, CodeGenRegisterClass *>>
422*0fca6ea1SDimitry Andric   getMatchingSubClassWithSubRegs(CodeGenRegBank &RegBank,
423*0fca6ea1SDimitry Andric                                  const CodeGenSubRegIndex *SubIdx) const;
424*0fca6ea1SDimitry Andric 
425*0fca6ea1SDimitry Andric   void setSubClassWithSubReg(const CodeGenSubRegIndex *SubIdx,
426*0fca6ea1SDimitry Andric                              CodeGenRegisterClass *SubRC) {
427*0fca6ea1SDimitry Andric     SubClassWithSubReg[SubIdx] = SubRC;
428*0fca6ea1SDimitry Andric   }
429*0fca6ea1SDimitry Andric 
430*0fca6ea1SDimitry Andric   // getSuperRegClasses - Returns a bit vector of all register classes
431*0fca6ea1SDimitry Andric   // containing only SubIdx super-registers of this class.
432*0fca6ea1SDimitry Andric   void getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,
433*0fca6ea1SDimitry Andric                           BitVector &Out) const;
434*0fca6ea1SDimitry Andric 
435*0fca6ea1SDimitry Andric   // addSuperRegClass - Add a class containing only SubIdx super-registers.
436*0fca6ea1SDimitry Andric   void addSuperRegClass(CodeGenSubRegIndex *SubIdx,
437*0fca6ea1SDimitry Andric                         CodeGenRegisterClass *SuperRC) {
438*0fca6ea1SDimitry Andric     SuperRegClasses[SubIdx].insert(SuperRC);
439*0fca6ea1SDimitry Andric   }
440*0fca6ea1SDimitry Andric 
441*0fca6ea1SDimitry Andric   // getSubClasses - Returns a constant BitVector of subclasses indexed by
442*0fca6ea1SDimitry Andric   // EnumValue.
443*0fca6ea1SDimitry Andric   // The SubClasses vector includes an entry for this class.
444*0fca6ea1SDimitry Andric   const BitVector &getSubClasses() const { return SubClasses; }
445*0fca6ea1SDimitry Andric 
446*0fca6ea1SDimitry Andric   // getSuperClasses - Returns a list of super classes ordered by EnumValue.
447*0fca6ea1SDimitry Andric   // The array does not include an entry for this class.
448*0fca6ea1SDimitry Andric   ArrayRef<CodeGenRegisterClass *> getSuperClasses() const {
449*0fca6ea1SDimitry Andric     return SuperClasses;
450*0fca6ea1SDimitry Andric   }
451*0fca6ea1SDimitry Andric 
452*0fca6ea1SDimitry Andric   // Returns an ordered list of class members.
453*0fca6ea1SDimitry Andric   // The order of registers is the same as in the .td file.
454*0fca6ea1SDimitry Andric   // No = 0 is the default allocation order, No = 1 is the first alternative.
455*0fca6ea1SDimitry Andric   ArrayRef<Record *> getOrder(unsigned No = 0) const { return Orders[No]; }
456*0fca6ea1SDimitry Andric 
457*0fca6ea1SDimitry Andric   // Return the total number of allocation orders available.
458*0fca6ea1SDimitry Andric   unsigned getNumOrders() const { return Orders.size(); }
459*0fca6ea1SDimitry Andric 
460*0fca6ea1SDimitry Andric   // Get the set of registers.  This set contains the same registers as
461*0fca6ea1SDimitry Andric   // getOrder(0).
462*0fca6ea1SDimitry Andric   const CodeGenRegister::Vec &getMembers() const { return Members; }
463*0fca6ea1SDimitry Andric 
464*0fca6ea1SDimitry Andric   // Get a bit vector of TopoSigs present in this register class.
465*0fca6ea1SDimitry Andric   const BitVector &getTopoSigs() const { return TopoSigs; }
466*0fca6ea1SDimitry Andric 
467*0fca6ea1SDimitry Andric   // Get a weight of this register class.
468*0fca6ea1SDimitry Andric   unsigned getWeight(const CodeGenRegBank &) const;
469*0fca6ea1SDimitry Andric 
470*0fca6ea1SDimitry Andric   // Populate a unique sorted list of units from a register set.
471*0fca6ea1SDimitry Andric   void buildRegUnitSet(const CodeGenRegBank &RegBank,
472*0fca6ea1SDimitry Andric                        std::vector<unsigned> &RegUnits) const;
473*0fca6ea1SDimitry Andric 
474*0fca6ea1SDimitry Andric   CodeGenRegisterClass(CodeGenRegBank &, Record *R);
475*0fca6ea1SDimitry Andric   CodeGenRegisterClass(CodeGenRegisterClass &) = delete;
476*0fca6ea1SDimitry Andric 
477*0fca6ea1SDimitry Andric   // A key representing the parts of a register class used for forming
478*0fca6ea1SDimitry Andric   // sub-classes.  Note the ordering provided by this key is not the same as
479*0fca6ea1SDimitry Andric   // the topological order used for the EnumValues.
480*0fca6ea1SDimitry Andric   struct Key {
481*0fca6ea1SDimitry Andric     const CodeGenRegister::Vec *Members;
482*0fca6ea1SDimitry Andric     RegSizeInfoByHwMode RSI;
483*0fca6ea1SDimitry Andric 
484*0fca6ea1SDimitry Andric     Key(const CodeGenRegister::Vec *M, const RegSizeInfoByHwMode &I)
485*0fca6ea1SDimitry Andric         : Members(M), RSI(I) {}
486*0fca6ea1SDimitry Andric 
487*0fca6ea1SDimitry Andric     Key(const CodeGenRegisterClass &RC)
488*0fca6ea1SDimitry Andric         : Members(&RC.getMembers()), RSI(RC.RSI) {}
489*0fca6ea1SDimitry Andric 
490*0fca6ea1SDimitry Andric     // Lexicographical order of (Members, RegSizeInfoByHwMode).
491*0fca6ea1SDimitry Andric     bool operator<(const Key &) const;
492*0fca6ea1SDimitry Andric   };
493*0fca6ea1SDimitry Andric 
494*0fca6ea1SDimitry Andric   // Create a non-user defined register class.
495*0fca6ea1SDimitry Andric   CodeGenRegisterClass(CodeGenRegBank &, StringRef Name, Key Props);
496*0fca6ea1SDimitry Andric 
497*0fca6ea1SDimitry Andric   // Called by CodeGenRegBank::CodeGenRegBank().
498*0fca6ea1SDimitry Andric   static void computeSubClasses(CodeGenRegBank &);
499*0fca6ea1SDimitry Andric 
500*0fca6ea1SDimitry Andric   // Get ordering value among register base classes.
501*0fca6ea1SDimitry Andric   std::optional<int> getBaseClassOrder() const {
502*0fca6ea1SDimitry Andric     if (TheDef && !TheDef->isValueUnset("BaseClassOrder"))
503*0fca6ea1SDimitry Andric       return TheDef->getValueAsInt("BaseClassOrder");
504*0fca6ea1SDimitry Andric     return {};
505*0fca6ea1SDimitry Andric   }
506*0fca6ea1SDimitry Andric };
507*0fca6ea1SDimitry Andric 
508*0fca6ea1SDimitry Andric // Register categories are used when we need to deterine the category a
509*0fca6ea1SDimitry Andric // register falls into (GPR, vector, fixed, etc.) without having to know
510*0fca6ea1SDimitry Andric // specific information about the target architecture.
511*0fca6ea1SDimitry Andric class CodeGenRegisterCategory {
512*0fca6ea1SDimitry Andric   Record *TheDef;
513*0fca6ea1SDimitry Andric   std::string Name;
514*0fca6ea1SDimitry Andric   std::list<CodeGenRegisterClass *> Classes;
515*0fca6ea1SDimitry Andric 
516*0fca6ea1SDimitry Andric public:
517*0fca6ea1SDimitry Andric   CodeGenRegisterCategory(CodeGenRegBank &, Record *R);
518*0fca6ea1SDimitry Andric   CodeGenRegisterCategory(CodeGenRegisterCategory &) = delete;
519*0fca6ea1SDimitry Andric 
520*0fca6ea1SDimitry Andric   // Return the Record that defined this class, or NULL if the class was
521*0fca6ea1SDimitry Andric   // created by TableGen.
522*0fca6ea1SDimitry Andric   Record *getDef() const { return TheDef; }
523*0fca6ea1SDimitry Andric 
524*0fca6ea1SDimitry Andric   std::string getName() const { return Name; }
525*0fca6ea1SDimitry Andric   std::list<CodeGenRegisterClass *> getClasses() const { return Classes; }
526*0fca6ea1SDimitry Andric };
527*0fca6ea1SDimitry Andric 
528*0fca6ea1SDimitry Andric // Register units are used to model interference and register pressure.
529*0fca6ea1SDimitry Andric // Every register is assigned one or more register units such that two
530*0fca6ea1SDimitry Andric // registers overlap if and only if they have a register unit in common.
531*0fca6ea1SDimitry Andric //
532*0fca6ea1SDimitry Andric // Normally, one register unit is created per leaf register. Non-leaf
533*0fca6ea1SDimitry Andric // registers inherit the units of their sub-registers.
534*0fca6ea1SDimitry Andric struct RegUnit {
535*0fca6ea1SDimitry Andric   // Weight assigned to this RegUnit for estimating register pressure.
536*0fca6ea1SDimitry Andric   // This is useful when equalizing weights in register classes with mixed
537*0fca6ea1SDimitry Andric   // register topologies.
538*0fca6ea1SDimitry Andric   unsigned Weight;
539*0fca6ea1SDimitry Andric 
540*0fca6ea1SDimitry Andric   // Each native RegUnit corresponds to one or two root registers. The full
541*0fca6ea1SDimitry Andric   // set of registers containing this unit can be computed as the union of
542*0fca6ea1SDimitry Andric   // these two registers and their super-registers.
543*0fca6ea1SDimitry Andric   const CodeGenRegister *Roots[2];
544*0fca6ea1SDimitry Andric 
545*0fca6ea1SDimitry Andric   // Index into RegClassUnitSets where we can find the list of UnitSets that
546*0fca6ea1SDimitry Andric   // contain this unit.
547*0fca6ea1SDimitry Andric   unsigned RegClassUnitSetsIdx;
548*0fca6ea1SDimitry Andric   // A register unit is artificial if at least one of its roots is
549*0fca6ea1SDimitry Andric   // artificial.
550*0fca6ea1SDimitry Andric   bool Artificial;
551*0fca6ea1SDimitry Andric 
552*0fca6ea1SDimitry Andric   RegUnit() : Weight(0), RegClassUnitSetsIdx(0), Artificial(false) {
553*0fca6ea1SDimitry Andric     Roots[0] = Roots[1] = nullptr;
554*0fca6ea1SDimitry Andric   }
555*0fca6ea1SDimitry Andric 
556*0fca6ea1SDimitry Andric   ArrayRef<const CodeGenRegister *> getRoots() const {
557*0fca6ea1SDimitry Andric     assert(!(Roots[1] && !Roots[0]) && "Invalid roots array");
558*0fca6ea1SDimitry Andric     return ArrayRef(Roots, !!Roots[0] + !!Roots[1]);
559*0fca6ea1SDimitry Andric   }
560*0fca6ea1SDimitry Andric };
561*0fca6ea1SDimitry Andric 
562*0fca6ea1SDimitry Andric // Each RegUnitSet is a sorted vector with a name.
563*0fca6ea1SDimitry Andric struct RegUnitSet {
564*0fca6ea1SDimitry Andric   typedef std::vector<unsigned>::const_iterator iterator;
565*0fca6ea1SDimitry Andric 
566*0fca6ea1SDimitry Andric   std::string Name;
567*0fca6ea1SDimitry Andric   std::vector<unsigned> Units;
568*0fca6ea1SDimitry Andric   unsigned Weight = 0; // Cache the sum of all unit weights.
569*0fca6ea1SDimitry Andric   unsigned Order = 0;  // Cache the sort key.
570*0fca6ea1SDimitry Andric 
571*0fca6ea1SDimitry Andric   RegUnitSet(std::string Name) : Name(Name) {}
572*0fca6ea1SDimitry Andric };
573*0fca6ea1SDimitry Andric 
574*0fca6ea1SDimitry Andric // Base vector for identifying TopoSigs. The contents uniquely identify a
575*0fca6ea1SDimitry Andric // TopoSig, only computeSuperRegs needs to know how.
576*0fca6ea1SDimitry Andric typedef SmallVector<unsigned, 16> TopoSigId;
577*0fca6ea1SDimitry Andric 
578*0fca6ea1SDimitry Andric // CodeGenRegBank - Represent a target's registers and the relations between
579*0fca6ea1SDimitry Andric // them.
580*0fca6ea1SDimitry Andric class CodeGenRegBank {
581*0fca6ea1SDimitry Andric   SetTheory Sets;
582*0fca6ea1SDimitry Andric 
583*0fca6ea1SDimitry Andric   const CodeGenHwModes &CGH;
584*0fca6ea1SDimitry Andric 
585*0fca6ea1SDimitry Andric   std::deque<CodeGenSubRegIndex> SubRegIndices;
586*0fca6ea1SDimitry Andric   DenseMap<Record *, CodeGenSubRegIndex *> Def2SubRegIdx;
587*0fca6ea1SDimitry Andric 
588*0fca6ea1SDimitry Andric   CodeGenSubRegIndex *createSubRegIndex(StringRef Name, StringRef NameSpace);
589*0fca6ea1SDimitry Andric 
590*0fca6ea1SDimitry Andric   typedef std::map<SmallVector<CodeGenSubRegIndex *, 8>, CodeGenSubRegIndex *>
591*0fca6ea1SDimitry Andric       ConcatIdxMap;
592*0fca6ea1SDimitry Andric   ConcatIdxMap ConcatIdx;
593*0fca6ea1SDimitry Andric 
594*0fca6ea1SDimitry Andric   // Registers.
595*0fca6ea1SDimitry Andric   std::deque<CodeGenRegister> Registers;
596*0fca6ea1SDimitry Andric   StringMap<CodeGenRegister *> RegistersByName;
597*0fca6ea1SDimitry Andric   DenseMap<Record *, CodeGenRegister *> Def2Reg;
598*0fca6ea1SDimitry Andric   unsigned NumNativeRegUnits;
599*0fca6ea1SDimitry Andric 
600*0fca6ea1SDimitry Andric   std::map<TopoSigId, unsigned> TopoSigs;
601*0fca6ea1SDimitry Andric 
602*0fca6ea1SDimitry Andric   // Includes native (0..NumNativeRegUnits-1) and adopted register units.
603*0fca6ea1SDimitry Andric   SmallVector<RegUnit, 8> RegUnits;
604*0fca6ea1SDimitry Andric 
605*0fca6ea1SDimitry Andric   // Register classes.
606*0fca6ea1SDimitry Andric   std::list<CodeGenRegisterClass> RegClasses;
607*0fca6ea1SDimitry Andric   DenseMap<Record *, CodeGenRegisterClass *> Def2RC;
608*0fca6ea1SDimitry Andric   typedef std::map<CodeGenRegisterClass::Key, CodeGenRegisterClass *> RCKeyMap;
609*0fca6ea1SDimitry Andric   RCKeyMap Key2RC;
610*0fca6ea1SDimitry Andric 
611*0fca6ea1SDimitry Andric   // Register categories.
612*0fca6ea1SDimitry Andric   std::list<CodeGenRegisterCategory> RegCategories;
613*0fca6ea1SDimitry Andric   DenseMap<Record *, CodeGenRegisterCategory *> Def2RCat;
614*0fca6ea1SDimitry Andric   using RCatKeyMap =
615*0fca6ea1SDimitry Andric       std::map<CodeGenRegisterClass::Key, CodeGenRegisterCategory *>;
616*0fca6ea1SDimitry Andric   RCatKeyMap Key2RCat;
617*0fca6ea1SDimitry Andric 
618*0fca6ea1SDimitry Andric   // Remember each unique set of register units. Initially, this contains a
619*0fca6ea1SDimitry Andric   // unique set for each register class. Simliar sets are coalesced with
620*0fca6ea1SDimitry Andric   // pruneUnitSets and new supersets are inferred during computeRegUnitSets.
621*0fca6ea1SDimitry Andric   std::vector<RegUnitSet> RegUnitSets;
622*0fca6ea1SDimitry Andric 
623*0fca6ea1SDimitry Andric   // Map RegisterClass index to the index of the RegUnitSet that contains the
624*0fca6ea1SDimitry Andric   // class's units and any inferred RegUnit supersets.
625*0fca6ea1SDimitry Andric   //
626*0fca6ea1SDimitry Andric   // NOTE: This could grow beyond the number of register classes when we map
627*0fca6ea1SDimitry Andric   // register units to lists of unit sets. If the list of unit sets does not
628*0fca6ea1SDimitry Andric   // already exist for a register class, we create a new entry in this vector.
629*0fca6ea1SDimitry Andric   std::vector<std::vector<unsigned>> RegClassUnitSets;
630*0fca6ea1SDimitry Andric 
631*0fca6ea1SDimitry Andric   // Give each register unit set an order based on sorting criteria.
632*0fca6ea1SDimitry Andric   std::vector<unsigned> RegUnitSetOrder;
633*0fca6ea1SDimitry Andric 
634*0fca6ea1SDimitry Andric   // Keep track of synthesized definitions generated in TupleExpander.
635*0fca6ea1SDimitry Andric   std::vector<std::unique_ptr<Record>> SynthDefs;
636*0fca6ea1SDimitry Andric 
637*0fca6ea1SDimitry Andric   // Add RC to *2RC maps.
638*0fca6ea1SDimitry Andric   void addToMaps(CodeGenRegisterClass *);
639*0fca6ea1SDimitry Andric 
640*0fca6ea1SDimitry Andric   // Create a synthetic sub-class if it is missing.
641*0fca6ea1SDimitry Andric   CodeGenRegisterClass *getOrCreateSubClass(const CodeGenRegisterClass *RC,
642*0fca6ea1SDimitry Andric                                             const CodeGenRegister::Vec *Membs,
643*0fca6ea1SDimitry Andric                                             StringRef Name);
644*0fca6ea1SDimitry Andric 
645*0fca6ea1SDimitry Andric   // Infer missing register classes.
646*0fca6ea1SDimitry Andric   void computeInferredRegisterClasses();
647*0fca6ea1SDimitry Andric   void inferCommonSubClass(CodeGenRegisterClass *RC);
648*0fca6ea1SDimitry Andric   void inferSubClassWithSubReg(CodeGenRegisterClass *RC);
649*0fca6ea1SDimitry Andric 
650*0fca6ea1SDimitry Andric   void inferMatchingSuperRegClass(CodeGenRegisterClass *RC) {
651*0fca6ea1SDimitry Andric     inferMatchingSuperRegClass(RC, RegClasses.begin());
652*0fca6ea1SDimitry Andric   }
653*0fca6ea1SDimitry Andric 
654*0fca6ea1SDimitry Andric   void inferMatchingSuperRegClass(
655*0fca6ea1SDimitry Andric       CodeGenRegisterClass *RC,
656*0fca6ea1SDimitry Andric       std::list<CodeGenRegisterClass>::iterator FirstSubRegRC);
657*0fca6ea1SDimitry Andric 
658*0fca6ea1SDimitry Andric   // Iteratively prune unit sets.
659*0fca6ea1SDimitry Andric   void pruneUnitSets();
660*0fca6ea1SDimitry Andric 
661*0fca6ea1SDimitry Andric   // Compute a weight for each register unit created during getSubRegs.
662*0fca6ea1SDimitry Andric   void computeRegUnitWeights();
663*0fca6ea1SDimitry Andric 
664*0fca6ea1SDimitry Andric   // Create a RegUnitSet for each RegClass and infer superclasses.
665*0fca6ea1SDimitry Andric   void computeRegUnitSets();
666*0fca6ea1SDimitry Andric 
667*0fca6ea1SDimitry Andric   // Populate the Composite map from sub-register relationships.
668*0fca6ea1SDimitry Andric   void computeComposites();
669*0fca6ea1SDimitry Andric 
670*0fca6ea1SDimitry Andric   // Compute a lane mask for each sub-register index.
671*0fca6ea1SDimitry Andric   void computeSubRegLaneMasks();
672*0fca6ea1SDimitry Andric 
673*0fca6ea1SDimitry Andric   /// Computes a lane mask for each register unit enumerated by a physical
674*0fca6ea1SDimitry Andric   /// register.
675*0fca6ea1SDimitry Andric   void computeRegUnitLaneMasks();
676*0fca6ea1SDimitry Andric 
677*0fca6ea1SDimitry Andric public:
678*0fca6ea1SDimitry Andric   CodeGenRegBank(RecordKeeper &, const CodeGenHwModes &);
679*0fca6ea1SDimitry Andric   CodeGenRegBank(CodeGenRegBank &) = delete;
680*0fca6ea1SDimitry Andric 
681*0fca6ea1SDimitry Andric   SetTheory &getSets() { return Sets; }
682*0fca6ea1SDimitry Andric 
683*0fca6ea1SDimitry Andric   const CodeGenHwModes &getHwModes() const { return CGH; }
684*0fca6ea1SDimitry Andric 
685*0fca6ea1SDimitry Andric   // Sub-register indices. The first NumNamedIndices are defined by the user
686*0fca6ea1SDimitry Andric   // in the .td files. The rest are synthesized such that all sub-registers
687*0fca6ea1SDimitry Andric   // have a unique name.
688*0fca6ea1SDimitry Andric   const std::deque<CodeGenSubRegIndex> &getSubRegIndices() const {
689*0fca6ea1SDimitry Andric     return SubRegIndices;
690*0fca6ea1SDimitry Andric   }
691*0fca6ea1SDimitry Andric 
692*0fca6ea1SDimitry Andric   // Find a SubRegIndex from its Record def or add to the list if it does
693*0fca6ea1SDimitry Andric   // not exist there yet.
694*0fca6ea1SDimitry Andric   CodeGenSubRegIndex *getSubRegIdx(Record *);
695*0fca6ea1SDimitry Andric 
696*0fca6ea1SDimitry Andric   // Find a SubRegIndex from its Record def.
697*0fca6ea1SDimitry Andric   const CodeGenSubRegIndex *findSubRegIdx(const Record *Def) const;
698*0fca6ea1SDimitry Andric 
699*0fca6ea1SDimitry Andric   // Find or create a sub-register index representing the A+B composition.
700*0fca6ea1SDimitry Andric   CodeGenSubRegIndex *getCompositeSubRegIndex(CodeGenSubRegIndex *A,
701*0fca6ea1SDimitry Andric                                               CodeGenSubRegIndex *B);
702*0fca6ea1SDimitry Andric 
703*0fca6ea1SDimitry Andric   // Find or create a sub-register index representing the concatenation of
704*0fca6ea1SDimitry Andric   // non-overlapping sibling indices.
705*0fca6ea1SDimitry Andric   CodeGenSubRegIndex *
706*0fca6ea1SDimitry Andric   getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8> &,
707*0fca6ea1SDimitry Andric                        const CodeGenHwModes &CGH);
708*0fca6ea1SDimitry Andric 
709*0fca6ea1SDimitry Andric   const std::deque<CodeGenRegister> &getRegisters() const { return Registers; }
710*0fca6ea1SDimitry Andric 
711*0fca6ea1SDimitry Andric   const StringMap<CodeGenRegister *> &getRegistersByName() const {
712*0fca6ea1SDimitry Andric     return RegistersByName;
713*0fca6ea1SDimitry Andric   }
714*0fca6ea1SDimitry Andric 
715*0fca6ea1SDimitry Andric   // Find a register from its Record def.
716*0fca6ea1SDimitry Andric   CodeGenRegister *getReg(Record *);
717*0fca6ea1SDimitry Andric 
718*0fca6ea1SDimitry Andric   // Get a Register's index into the Registers array.
719*0fca6ea1SDimitry Andric   unsigned getRegIndex(const CodeGenRegister *Reg) const {
720*0fca6ea1SDimitry Andric     return Reg->EnumValue - 1;
721*0fca6ea1SDimitry Andric   }
722*0fca6ea1SDimitry Andric 
723*0fca6ea1SDimitry Andric   // Return the number of allocated TopoSigs. The first TopoSig representing
724*0fca6ea1SDimitry Andric   // leaf registers is allocated number 0.
725*0fca6ea1SDimitry Andric   unsigned getNumTopoSigs() const { return TopoSigs.size(); }
726*0fca6ea1SDimitry Andric 
727*0fca6ea1SDimitry Andric   // Find or create a TopoSig for the given TopoSigId.
728*0fca6ea1SDimitry Andric   // This function is only for use by CodeGenRegister::computeSuperRegs().
729*0fca6ea1SDimitry Andric   // Others should simply use Reg->getTopoSig().
730*0fca6ea1SDimitry Andric   unsigned getTopoSig(const TopoSigId &Id) {
731*0fca6ea1SDimitry Andric     return TopoSigs.insert(std::pair(Id, TopoSigs.size())).first->second;
732*0fca6ea1SDimitry Andric   }
733*0fca6ea1SDimitry Andric 
734*0fca6ea1SDimitry Andric   // Create a native register unit that is associated with one or two root
735*0fca6ea1SDimitry Andric   // registers.
736*0fca6ea1SDimitry Andric   unsigned newRegUnit(CodeGenRegister *R0, CodeGenRegister *R1 = nullptr) {
737*0fca6ea1SDimitry Andric     RegUnit &RU = RegUnits.emplace_back();
738*0fca6ea1SDimitry Andric     RU.Roots[0] = R0;
739*0fca6ea1SDimitry Andric     RU.Roots[1] = R1;
740*0fca6ea1SDimitry Andric     RU.Artificial = R0->Artificial;
741*0fca6ea1SDimitry Andric     if (R1)
742*0fca6ea1SDimitry Andric       RU.Artificial |= R1->Artificial;
743*0fca6ea1SDimitry Andric     return RegUnits.size() - 1;
744*0fca6ea1SDimitry Andric   }
745*0fca6ea1SDimitry Andric 
746*0fca6ea1SDimitry Andric   // Create a new non-native register unit that can be adopted by a register
747*0fca6ea1SDimitry Andric   // to increase its pressure. Note that NumNativeRegUnits is not increased.
748*0fca6ea1SDimitry Andric   unsigned newRegUnit(unsigned Weight) {
749*0fca6ea1SDimitry Andric     RegUnit &RU = RegUnits.emplace_back();
750*0fca6ea1SDimitry Andric     RU.Weight = Weight;
751*0fca6ea1SDimitry Andric     return RegUnits.size() - 1;
752*0fca6ea1SDimitry Andric   }
753*0fca6ea1SDimitry Andric 
754*0fca6ea1SDimitry Andric   // Native units are the singular unit of a leaf register. Register aliasing
755*0fca6ea1SDimitry Andric   // is completely characterized by native units. Adopted units exist to give
756*0fca6ea1SDimitry Andric   // register additional weight but don't affect aliasing.
757*0fca6ea1SDimitry Andric   bool isNativeUnit(unsigned RUID) const { return RUID < NumNativeRegUnits; }
758*0fca6ea1SDimitry Andric 
759*0fca6ea1SDimitry Andric   unsigned getNumNativeRegUnits() const { return NumNativeRegUnits; }
760*0fca6ea1SDimitry Andric 
761*0fca6ea1SDimitry Andric   RegUnit &getRegUnit(unsigned RUID) { return RegUnits[RUID]; }
762*0fca6ea1SDimitry Andric   const RegUnit &getRegUnit(unsigned RUID) const { return RegUnits[RUID]; }
763*0fca6ea1SDimitry Andric 
764*0fca6ea1SDimitry Andric   std::list<CodeGenRegisterClass> &getRegClasses() { return RegClasses; }
765*0fca6ea1SDimitry Andric 
766*0fca6ea1SDimitry Andric   const std::list<CodeGenRegisterClass> &getRegClasses() const {
767*0fca6ea1SDimitry Andric     return RegClasses;
768*0fca6ea1SDimitry Andric   }
769*0fca6ea1SDimitry Andric 
770*0fca6ea1SDimitry Andric   std::list<CodeGenRegisterCategory> &getRegCategories() {
771*0fca6ea1SDimitry Andric     return RegCategories;
772*0fca6ea1SDimitry Andric   }
773*0fca6ea1SDimitry Andric 
774*0fca6ea1SDimitry Andric   const std::list<CodeGenRegisterCategory> &getRegCategories() const {
775*0fca6ea1SDimitry Andric     return RegCategories;
776*0fca6ea1SDimitry Andric   }
777*0fca6ea1SDimitry Andric 
778*0fca6ea1SDimitry Andric   // Find a register class from its def.
779*0fca6ea1SDimitry Andric   CodeGenRegisterClass *getRegClass(const Record *) const;
780*0fca6ea1SDimitry Andric 
781*0fca6ea1SDimitry Andric   /// getRegisterClassForRegister - Find the register class that contains the
782*0fca6ea1SDimitry Andric   /// specified physical register.  If the register is not in a register
783*0fca6ea1SDimitry Andric   /// class, return null. If the register is in multiple classes, and the
784*0fca6ea1SDimitry Andric   /// classes have a superset-subset relationship and the same set of types,
785*0fca6ea1SDimitry Andric   /// return the superclass.  Otherwise return null.
786*0fca6ea1SDimitry Andric   const CodeGenRegisterClass *getRegClassForRegister(Record *R);
787*0fca6ea1SDimitry Andric 
788*0fca6ea1SDimitry Andric   // Analog of TargetRegisterInfo::getMinimalPhysRegClass. Unlike
789*0fca6ea1SDimitry Andric   // getRegClassForRegister, this tries to find the smallest class containing
790*0fca6ea1SDimitry Andric   // the physical register. If \p VT is specified, it will only find classes
791*0fca6ea1SDimitry Andric   // with a matching type
792*0fca6ea1SDimitry Andric   const CodeGenRegisterClass *
793*0fca6ea1SDimitry Andric   getMinimalPhysRegClass(Record *RegRecord, ValueTypeByHwMode *VT = nullptr);
794*0fca6ea1SDimitry Andric 
795*0fca6ea1SDimitry Andric   // Get the sum of unit weights.
796*0fca6ea1SDimitry Andric   unsigned getRegUnitSetWeight(const std::vector<unsigned> &Units) const {
797*0fca6ea1SDimitry Andric     unsigned Weight = 0;
798*0fca6ea1SDimitry Andric     for (unsigned Unit : Units)
799*0fca6ea1SDimitry Andric       Weight += getRegUnit(Unit).Weight;
800*0fca6ea1SDimitry Andric     return Weight;
801*0fca6ea1SDimitry Andric   }
802*0fca6ea1SDimitry Andric 
803*0fca6ea1SDimitry Andric   unsigned getRegSetIDAt(unsigned Order) const {
804*0fca6ea1SDimitry Andric     return RegUnitSetOrder[Order];
805*0fca6ea1SDimitry Andric   }
806*0fca6ea1SDimitry Andric 
807*0fca6ea1SDimitry Andric   const RegUnitSet &getRegSetAt(unsigned Order) const {
808*0fca6ea1SDimitry Andric     return RegUnitSets[RegUnitSetOrder[Order]];
809*0fca6ea1SDimitry Andric   }
810*0fca6ea1SDimitry Andric 
811*0fca6ea1SDimitry Andric   // Increase a RegUnitWeight.
812*0fca6ea1SDimitry Andric   void increaseRegUnitWeight(unsigned RUID, unsigned Inc) {
813*0fca6ea1SDimitry Andric     getRegUnit(RUID).Weight += Inc;
814*0fca6ea1SDimitry Andric   }
815*0fca6ea1SDimitry Andric 
816*0fca6ea1SDimitry Andric   // Get the number of register pressure dimensions.
817*0fca6ea1SDimitry Andric   unsigned getNumRegPressureSets() const { return RegUnitSets.size(); }
818*0fca6ea1SDimitry Andric 
819*0fca6ea1SDimitry Andric   // Get a set of register unit IDs for a given dimension of pressure.
820*0fca6ea1SDimitry Andric   const RegUnitSet &getRegPressureSet(unsigned Idx) const {
821*0fca6ea1SDimitry Andric     return RegUnitSets[Idx];
822*0fca6ea1SDimitry Andric   }
823*0fca6ea1SDimitry Andric 
824*0fca6ea1SDimitry Andric   // The number of pressure set lists may be larget than the number of
825*0fca6ea1SDimitry Andric   // register classes if some register units appeared in a list of sets that
826*0fca6ea1SDimitry Andric   // did not correspond to an existing register class.
827*0fca6ea1SDimitry Andric   unsigned getNumRegClassPressureSetLists() const {
828*0fca6ea1SDimitry Andric     return RegClassUnitSets.size();
829*0fca6ea1SDimitry Andric   }
830*0fca6ea1SDimitry Andric 
831*0fca6ea1SDimitry Andric   // Get a list of pressure set IDs for a register class. Liveness of a
832*0fca6ea1SDimitry Andric   // register in this class impacts each pressure set in this list by the
833*0fca6ea1SDimitry Andric   // weight of the register. An exact solution requires all registers in a
834*0fca6ea1SDimitry Andric   // class to have the same class, but it is not strictly guaranteed.
835*0fca6ea1SDimitry Andric   ArrayRef<unsigned> getRCPressureSetIDs(unsigned RCIdx) const {
836*0fca6ea1SDimitry Andric     return RegClassUnitSets[RCIdx];
837*0fca6ea1SDimitry Andric   }
838*0fca6ea1SDimitry Andric 
839*0fca6ea1SDimitry Andric   // Computed derived records such as missing sub-register indices.
840*0fca6ea1SDimitry Andric   void computeDerivedInfo();
841*0fca6ea1SDimitry Andric 
842*0fca6ea1SDimitry Andric   // Compute the set of registers completely covered by the registers in Regs.
843*0fca6ea1SDimitry Andric   // The returned BitVector will have a bit set for each register in Regs,
844*0fca6ea1SDimitry Andric   // all sub-registers, and all super-registers that are covered by the
845*0fca6ea1SDimitry Andric   // registers in Regs.
846*0fca6ea1SDimitry Andric   //
847*0fca6ea1SDimitry Andric   // This is used to compute the mask of call-preserved registers from a list
848*0fca6ea1SDimitry Andric   // of callee-saves.
849*0fca6ea1SDimitry Andric   BitVector computeCoveredRegisters(ArrayRef<Record *> Regs);
850*0fca6ea1SDimitry Andric 
851*0fca6ea1SDimitry Andric   // Bit mask of lanes that cover their registers. A sub-register index whose
852*0fca6ea1SDimitry Andric   // LaneMask is contained in CoveringLanes will be completely covered by
853*0fca6ea1SDimitry Andric   // another sub-register with the same or larger lane mask.
854*0fca6ea1SDimitry Andric   LaneBitmask CoveringLanes;
855*0fca6ea1SDimitry Andric 
856*0fca6ea1SDimitry Andric   // Helper function for printing debug information. Handles artificial
857*0fca6ea1SDimitry Andric   // (non-native) reg units.
858*0fca6ea1SDimitry Andric   void printRegUnitName(unsigned Unit) const;
859*0fca6ea1SDimitry Andric };
860*0fca6ea1SDimitry Andric 
861*0fca6ea1SDimitry Andric } // end namespace llvm
862*0fca6ea1SDimitry Andric 
863*0fca6ea1SDimitry Andric #endif // LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H
864