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