xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/Common/InfoByHwMode.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===--- InfoByHwMode.h -----------------------------------------*- 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 // Classes that implement data parameterized by HW modes for instruction
9*0fca6ea1SDimitry Andric // selection. Currently it is ValueTypeByHwMode (parameterized ValueType),
10*0fca6ea1SDimitry Andric // and RegSizeInfoByHwMode (parameterized register/spill size and alignment
11*0fca6ea1SDimitry Andric // data).
12*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
13*0fca6ea1SDimitry Andric 
14*0fca6ea1SDimitry Andric #ifndef LLVM_UTILS_TABLEGEN_INFOBYHWMODE_H
15*0fca6ea1SDimitry Andric #define LLVM_UTILS_TABLEGEN_INFOBYHWMODE_H
16*0fca6ea1SDimitry Andric 
17*0fca6ea1SDimitry Andric #include "CodeGenHwModes.h"
18*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallVector.h"
19*0fca6ea1SDimitry Andric #include "llvm/ADT/StringRef.h"
20*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h"
21*0fca6ea1SDimitry Andric #include "llvm/Support/Compiler.h"
22*0fca6ea1SDimitry Andric #include <cassert>
23*0fca6ea1SDimitry Andric #include <limits>
24*0fca6ea1SDimitry Andric #include <map>
25*0fca6ea1SDimitry Andric #include <string>
26*0fca6ea1SDimitry Andric #include <tuple>
27*0fca6ea1SDimitry Andric #include <utility>
28*0fca6ea1SDimitry Andric 
29*0fca6ea1SDimitry Andric namespace llvm {
30*0fca6ea1SDimitry Andric 
31*0fca6ea1SDimitry Andric class Record;
32*0fca6ea1SDimitry Andric class raw_ostream;
33*0fca6ea1SDimitry Andric 
34*0fca6ea1SDimitry Andric template <typename InfoT> struct InfoByHwMode;
35*0fca6ea1SDimitry Andric 
36*0fca6ea1SDimitry Andric std::string getModeName(unsigned Mode);
37*0fca6ea1SDimitry Andric 
38*0fca6ea1SDimitry Andric enum : unsigned {
39*0fca6ea1SDimitry Andric   DefaultMode = CodeGenHwModes::DefaultMode,
40*0fca6ea1SDimitry Andric };
41*0fca6ea1SDimitry Andric 
42*0fca6ea1SDimitry Andric template <typename InfoT>
43*0fca6ea1SDimitry Andric void union_modes(const InfoByHwMode<InfoT> &A, const InfoByHwMode<InfoT> &B,
44*0fca6ea1SDimitry Andric                  SmallVectorImpl<unsigned> &Modes) {
45*0fca6ea1SDimitry Andric   auto AI = A.begin();
46*0fca6ea1SDimitry Andric   auto BI = B.begin();
47*0fca6ea1SDimitry Andric 
48*0fca6ea1SDimitry Andric   // Skip default mode, but remember if we had one.
49*0fca6ea1SDimitry Andric   bool HasDefault = false;
50*0fca6ea1SDimitry Andric   if (AI != A.end() && AI->first == DefaultMode) {
51*0fca6ea1SDimitry Andric     HasDefault = true;
52*0fca6ea1SDimitry Andric     ++AI;
53*0fca6ea1SDimitry Andric   }
54*0fca6ea1SDimitry Andric   if (BI != B.end() && BI->first == DefaultMode) {
55*0fca6ea1SDimitry Andric     HasDefault = true;
56*0fca6ea1SDimitry Andric     ++BI;
57*0fca6ea1SDimitry Andric   }
58*0fca6ea1SDimitry Andric 
59*0fca6ea1SDimitry Andric   while (AI != A.end()) {
60*0fca6ea1SDimitry Andric     // If we're done with B, finish A.
61*0fca6ea1SDimitry Andric     if (BI == B.end()) {
62*0fca6ea1SDimitry Andric       for (; AI != A.end(); ++AI)
63*0fca6ea1SDimitry Andric         Modes.push_back(AI->first);
64*0fca6ea1SDimitry Andric       break;
65*0fca6ea1SDimitry Andric     }
66*0fca6ea1SDimitry Andric 
67*0fca6ea1SDimitry Andric     if (BI->first < AI->first) {
68*0fca6ea1SDimitry Andric       Modes.push_back(BI->first);
69*0fca6ea1SDimitry Andric       ++BI;
70*0fca6ea1SDimitry Andric     } else {
71*0fca6ea1SDimitry Andric       Modes.push_back(AI->first);
72*0fca6ea1SDimitry Andric       if (AI->first == BI->first)
73*0fca6ea1SDimitry Andric         ++BI;
74*0fca6ea1SDimitry Andric       ++AI;
75*0fca6ea1SDimitry Andric     }
76*0fca6ea1SDimitry Andric   }
77*0fca6ea1SDimitry Andric 
78*0fca6ea1SDimitry Andric   // Finish B.
79*0fca6ea1SDimitry Andric   for (; BI != B.end(); ++BI)
80*0fca6ea1SDimitry Andric     Modes.push_back(BI->first);
81*0fca6ea1SDimitry Andric 
82*0fca6ea1SDimitry Andric   // Make sure that the default mode is last on the list.
83*0fca6ea1SDimitry Andric   if (HasDefault)
84*0fca6ea1SDimitry Andric     Modes.push_back(DefaultMode);
85*0fca6ea1SDimitry Andric }
86*0fca6ea1SDimitry Andric 
87*0fca6ea1SDimitry Andric template <typename InfoT> struct InfoByHwMode {
88*0fca6ea1SDimitry Andric   typedef std::map<unsigned, InfoT> MapType;
89*0fca6ea1SDimitry Andric   typedef typename MapType::value_type PairType;
90*0fca6ea1SDimitry Andric   typedef typename MapType::iterator iterator;
91*0fca6ea1SDimitry Andric   typedef typename MapType::const_iterator const_iterator;
92*0fca6ea1SDimitry Andric 
93*0fca6ea1SDimitry Andric   InfoByHwMode() = default;
94*0fca6ea1SDimitry Andric   InfoByHwMode(const MapType &M) : Map(M) {}
95*0fca6ea1SDimitry Andric 
96*0fca6ea1SDimitry Andric   LLVM_ATTRIBUTE_ALWAYS_INLINE
97*0fca6ea1SDimitry Andric   iterator begin() { return Map.begin(); }
98*0fca6ea1SDimitry Andric   LLVM_ATTRIBUTE_ALWAYS_INLINE
99*0fca6ea1SDimitry Andric   iterator end() { return Map.end(); }
100*0fca6ea1SDimitry Andric   LLVM_ATTRIBUTE_ALWAYS_INLINE
101*0fca6ea1SDimitry Andric   const_iterator begin() const { return Map.begin(); }
102*0fca6ea1SDimitry Andric   LLVM_ATTRIBUTE_ALWAYS_INLINE
103*0fca6ea1SDimitry Andric   const_iterator end() const { return Map.end(); }
104*0fca6ea1SDimitry Andric   LLVM_ATTRIBUTE_ALWAYS_INLINE
105*0fca6ea1SDimitry Andric   bool empty() const { return Map.empty(); }
106*0fca6ea1SDimitry Andric 
107*0fca6ea1SDimitry Andric   LLVM_ATTRIBUTE_ALWAYS_INLINE
108*0fca6ea1SDimitry Andric   bool hasMode(unsigned M) const { return Map.find(M) != Map.end(); }
109*0fca6ea1SDimitry Andric   LLVM_ATTRIBUTE_ALWAYS_INLINE
110*0fca6ea1SDimitry Andric   bool hasDefault() const {
111*0fca6ea1SDimitry Andric     return !Map.empty() && Map.begin()->first == DefaultMode;
112*0fca6ea1SDimitry Andric   }
113*0fca6ea1SDimitry Andric 
114*0fca6ea1SDimitry Andric   InfoT &get(unsigned Mode) {
115*0fca6ea1SDimitry Andric     auto F = Map.find(Mode);
116*0fca6ea1SDimitry Andric     if (F != Map.end())
117*0fca6ea1SDimitry Andric       return F->second;
118*0fca6ea1SDimitry Andric 
119*0fca6ea1SDimitry Andric     // Copy and insert the default mode which should be first.
120*0fca6ea1SDimitry Andric     assert(hasDefault());
121*0fca6ea1SDimitry Andric     auto P = Map.insert({Mode, Map.begin()->second});
122*0fca6ea1SDimitry Andric     return P.first->second;
123*0fca6ea1SDimitry Andric   }
124*0fca6ea1SDimitry Andric   const InfoT &get(unsigned Mode) const {
125*0fca6ea1SDimitry Andric     auto F = Map.find(Mode);
126*0fca6ea1SDimitry Andric     if (F != Map.end())
127*0fca6ea1SDimitry Andric       return F->second;
128*0fca6ea1SDimitry Andric     // Get the default mode which should be first.
129*0fca6ea1SDimitry Andric     F = Map.begin();
130*0fca6ea1SDimitry Andric     assert(F != Map.end() && F->first == DefaultMode);
131*0fca6ea1SDimitry Andric     return F->second;
132*0fca6ea1SDimitry Andric   }
133*0fca6ea1SDimitry Andric 
134*0fca6ea1SDimitry Andric   LLVM_ATTRIBUTE_ALWAYS_INLINE
135*0fca6ea1SDimitry Andric   bool isSimple() const {
136*0fca6ea1SDimitry Andric     return Map.size() == 1 && Map.begin()->first == DefaultMode;
137*0fca6ea1SDimitry Andric   }
138*0fca6ea1SDimitry Andric   LLVM_ATTRIBUTE_ALWAYS_INLINE
139*0fca6ea1SDimitry Andric   const InfoT &getSimple() const {
140*0fca6ea1SDimitry Andric     assert(isSimple());
141*0fca6ea1SDimitry Andric     return Map.begin()->second;
142*0fca6ea1SDimitry Andric   }
143*0fca6ea1SDimitry Andric   void makeSimple(unsigned Mode) {
144*0fca6ea1SDimitry Andric     assert(hasMode(Mode) || hasDefault());
145*0fca6ea1SDimitry Andric     InfoT I = get(Mode);
146*0fca6ea1SDimitry Andric     Map.clear();
147*0fca6ea1SDimitry Andric     Map.insert(std::pair(DefaultMode, I));
148*0fca6ea1SDimitry Andric   }
149*0fca6ea1SDimitry Andric 
150*0fca6ea1SDimitry Andric protected:
151*0fca6ea1SDimitry Andric   MapType Map;
152*0fca6ea1SDimitry Andric };
153*0fca6ea1SDimitry Andric 
154*0fca6ea1SDimitry Andric struct ValueTypeByHwMode : public InfoByHwMode<MVT> {
155*0fca6ea1SDimitry Andric   ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH);
156*0fca6ea1SDimitry Andric   ValueTypeByHwMode(Record *R, MVT T);
157*0fca6ea1SDimitry Andric   ValueTypeByHwMode(MVT T) { Map.insert({DefaultMode, T}); }
158*0fca6ea1SDimitry Andric   ValueTypeByHwMode() = default;
159*0fca6ea1SDimitry Andric 
160*0fca6ea1SDimitry Andric   bool operator==(const ValueTypeByHwMode &T) const;
161*0fca6ea1SDimitry Andric   bool operator<(const ValueTypeByHwMode &T) const;
162*0fca6ea1SDimitry Andric 
163*0fca6ea1SDimitry Andric   bool isValid() const { return !Map.empty(); }
164*0fca6ea1SDimitry Andric   MVT getType(unsigned Mode) const { return get(Mode); }
165*0fca6ea1SDimitry Andric   MVT &getOrCreateTypeForMode(unsigned Mode, MVT Type);
166*0fca6ea1SDimitry Andric 
167*0fca6ea1SDimitry Andric   static StringRef getMVTName(MVT T);
168*0fca6ea1SDimitry Andric   void writeToStream(raw_ostream &OS) const;
169*0fca6ea1SDimitry Andric   void dump() const;
170*0fca6ea1SDimitry Andric 
171*0fca6ea1SDimitry Andric   unsigned PtrAddrSpace = std::numeric_limits<unsigned>::max();
172*0fca6ea1SDimitry Andric   bool isPointer() const {
173*0fca6ea1SDimitry Andric     return PtrAddrSpace != std::numeric_limits<unsigned>::max();
174*0fca6ea1SDimitry Andric   }
175*0fca6ea1SDimitry Andric };
176*0fca6ea1SDimitry Andric 
177*0fca6ea1SDimitry Andric ValueTypeByHwMode getValueTypeByHwMode(Record *Rec, const CodeGenHwModes &CGH);
178*0fca6ea1SDimitry Andric 
179*0fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T);
180*0fca6ea1SDimitry Andric 
181*0fca6ea1SDimitry Andric struct RegSizeInfo {
182*0fca6ea1SDimitry Andric   unsigned RegSize;
183*0fca6ea1SDimitry Andric   unsigned SpillSize;
184*0fca6ea1SDimitry Andric   unsigned SpillAlignment;
185*0fca6ea1SDimitry Andric 
186*0fca6ea1SDimitry Andric   RegSizeInfo(Record *R);
187*0fca6ea1SDimitry Andric   RegSizeInfo() = default;
188*0fca6ea1SDimitry Andric   bool operator<(const RegSizeInfo &I) const;
189*0fca6ea1SDimitry Andric   bool operator==(const RegSizeInfo &I) const {
190*0fca6ea1SDimitry Andric     return std::tie(RegSize, SpillSize, SpillAlignment) ==
191*0fca6ea1SDimitry Andric            std::tie(I.RegSize, I.SpillSize, I.SpillAlignment);
192*0fca6ea1SDimitry Andric   }
193*0fca6ea1SDimitry Andric   bool operator!=(const RegSizeInfo &I) const { return !(*this == I); }
194*0fca6ea1SDimitry Andric 
195*0fca6ea1SDimitry Andric   bool isSubClassOf(const RegSizeInfo &I) const;
196*0fca6ea1SDimitry Andric   void writeToStream(raw_ostream &OS) const;
197*0fca6ea1SDimitry Andric };
198*0fca6ea1SDimitry Andric 
199*0fca6ea1SDimitry Andric struct RegSizeInfoByHwMode : public InfoByHwMode<RegSizeInfo> {
200*0fca6ea1SDimitry Andric   RegSizeInfoByHwMode(Record *R, const CodeGenHwModes &CGH);
201*0fca6ea1SDimitry Andric   RegSizeInfoByHwMode() = default;
202*0fca6ea1SDimitry Andric   bool operator<(const RegSizeInfoByHwMode &VI) const;
203*0fca6ea1SDimitry Andric   bool operator==(const RegSizeInfoByHwMode &VI) const;
204*0fca6ea1SDimitry Andric   bool operator!=(const RegSizeInfoByHwMode &VI) const {
205*0fca6ea1SDimitry Andric     return !(*this == VI);
206*0fca6ea1SDimitry Andric   }
207*0fca6ea1SDimitry Andric 
208*0fca6ea1SDimitry Andric   bool isSubClassOf(const RegSizeInfoByHwMode &I) const;
209*0fca6ea1SDimitry Andric   bool hasStricterSpillThan(const RegSizeInfoByHwMode &I) const;
210*0fca6ea1SDimitry Andric 
211*0fca6ea1SDimitry Andric   void writeToStream(raw_ostream &OS) const;
212*0fca6ea1SDimitry Andric 
213*0fca6ea1SDimitry Andric   void insertRegSizeForMode(unsigned Mode, RegSizeInfo Info) {
214*0fca6ea1SDimitry Andric     Map.insert(std::pair(Mode, Info));
215*0fca6ea1SDimitry Andric   }
216*0fca6ea1SDimitry Andric };
217*0fca6ea1SDimitry Andric 
218*0fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T);
219*0fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T);
220*0fca6ea1SDimitry Andric 
221*0fca6ea1SDimitry Andric struct SubRegRange {
222*0fca6ea1SDimitry Andric   uint16_t Size;
223*0fca6ea1SDimitry Andric   uint16_t Offset;
224*0fca6ea1SDimitry Andric 
225*0fca6ea1SDimitry Andric   SubRegRange(Record *R);
226*0fca6ea1SDimitry Andric   SubRegRange(uint16_t Size, uint16_t Offset) : Size(Size), Offset(Offset) {}
227*0fca6ea1SDimitry Andric };
228*0fca6ea1SDimitry Andric 
229*0fca6ea1SDimitry Andric struct SubRegRangeByHwMode : public InfoByHwMode<SubRegRange> {
230*0fca6ea1SDimitry Andric   SubRegRangeByHwMode(Record *R, const CodeGenHwModes &CGH);
231*0fca6ea1SDimitry Andric   SubRegRangeByHwMode(SubRegRange Range) { Map.insert({DefaultMode, Range}); }
232*0fca6ea1SDimitry Andric   SubRegRangeByHwMode() = default;
233*0fca6ea1SDimitry Andric 
234*0fca6ea1SDimitry Andric   void insertSubRegRangeForMode(unsigned Mode, SubRegRange Info) {
235*0fca6ea1SDimitry Andric     Map.insert(std::pair(Mode, Info));
236*0fca6ea1SDimitry Andric   }
237*0fca6ea1SDimitry Andric };
238*0fca6ea1SDimitry Andric 
239*0fca6ea1SDimitry Andric struct EncodingInfoByHwMode : public InfoByHwMode<Record *> {
240*0fca6ea1SDimitry Andric   EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH);
241*0fca6ea1SDimitry Andric   EncodingInfoByHwMode() = default;
242*0fca6ea1SDimitry Andric };
243*0fca6ea1SDimitry Andric 
244*0fca6ea1SDimitry Andric } // namespace llvm
245*0fca6ea1SDimitry Andric 
246*0fca6ea1SDimitry Andric #endif // LLVM_UTILS_TABLEGEN_INFOBYHWMODE_H
247