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_INFOBYHWMODE_H |
15 | #define LLVM_UTILS_TABLEGEN_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(Elt: AI->first); |
64 | break; |
65 | } |
66 | |
67 | if (BI->first < AI->first) { |
68 | Modes.push_back(Elt: BI->first); |
69 | ++BI; |
70 | } else { |
71 | Modes.push_back(Elt: 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(Elt: BI->first); |
81 | |
82 | // Make sure that the default mode is last on the list. |
83 | if (HasDefault) |
84 | Modes.push_back(Elt: 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.insert(std::pair(DefaultMode, I)); |
148 | } |
149 | |
150 | protected: |
151 | MapType Map; |
152 | }; |
153 | |
154 | struct ValueTypeByHwMode : public InfoByHwMode<MVT> { |
155 | ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH); |
156 | ValueTypeByHwMode(Record *R, MVT T); |
157 | ValueTypeByHwMode(MVT T) { Map.insert(x: {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(Record *Rec, const CodeGenHwModes &CGH); |
178 | |
179 | raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T); |
180 | |
181 | struct RegSizeInfo { |
182 | unsigned RegSize; |
183 | unsigned SpillSize; |
184 | unsigned SpillAlignment; |
185 | |
186 | RegSizeInfo(Record *R); |
187 | RegSizeInfo() = default; |
188 | bool operator<(const RegSizeInfo &I) const; |
189 | bool operator==(const RegSizeInfo &I) const { |
190 | return std::tie(args: RegSize, args: SpillSize, args: SpillAlignment) == |
191 | std::tie(args: I.RegSize, args: I.SpillSize, args: I.SpillAlignment); |
192 | } |
193 | bool operator!=(const RegSizeInfo &I) const { return !(*this == I); } |
194 | |
195 | bool isSubClassOf(const RegSizeInfo &I) const; |
196 | void writeToStream(raw_ostream &OS) const; |
197 | }; |
198 | |
199 | struct RegSizeInfoByHwMode : public InfoByHwMode<RegSizeInfo> { |
200 | RegSizeInfoByHwMode(Record *R, const CodeGenHwModes &CGH); |
201 | RegSizeInfoByHwMode() = default; |
202 | bool operator<(const RegSizeInfoByHwMode &VI) const; |
203 | bool operator==(const RegSizeInfoByHwMode &VI) const; |
204 | bool operator!=(const RegSizeInfoByHwMode &VI) const { |
205 | return !(*this == VI); |
206 | } |
207 | |
208 | bool isSubClassOf(const RegSizeInfoByHwMode &I) const; |
209 | bool hasStricterSpillThan(const RegSizeInfoByHwMode &I) const; |
210 | |
211 | void writeToStream(raw_ostream &OS) const; |
212 | |
213 | void insertRegSizeForMode(unsigned Mode, RegSizeInfo Info) { |
214 | Map.insert(x: std::pair(Mode, Info)); |
215 | } |
216 | }; |
217 | |
218 | raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T); |
219 | raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T); |
220 | |
221 | struct SubRegRange { |
222 | uint16_t Size; |
223 | uint16_t Offset; |
224 | |
225 | SubRegRange(Record *R); |
226 | SubRegRange(uint16_t Size, uint16_t Offset) : Size(Size), Offset(Offset) {} |
227 | }; |
228 | |
229 | struct SubRegRangeByHwMode : public InfoByHwMode<SubRegRange> { |
230 | SubRegRangeByHwMode(Record *R, const CodeGenHwModes &CGH); |
231 | SubRegRangeByHwMode(SubRegRange Range) { Map.insert(x: {DefaultMode, Range}); } |
232 | SubRegRangeByHwMode() = default; |
233 | |
234 | void insertSubRegRangeForMode(unsigned Mode, SubRegRange Info) { |
235 | Map.insert(x: std::pair(Mode, Info)); |
236 | } |
237 | }; |
238 | |
239 | struct EncodingInfoByHwMode : public InfoByHwMode<Record *> { |
240 | EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH); |
241 | EncodingInfoByHwMode() = default; |
242 | }; |
243 | |
244 | } // namespace llvm |
245 | |
246 | #endif // LLVM_UTILS_TABLEGEN_INFOBYHWMODE_H |
247 | |