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/CodeGen/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>
union_modes(const InfoByHwMode<InfoT> & A,const InfoByHwMode<InfoT> & B,SmallVectorImpl<unsigned> & Modes)43 void union_modes(const InfoByHwMode<InfoT> &A,
44 const InfoByHwMode<InfoT> &B,
45 SmallVectorImpl<unsigned> &Modes) {
46 auto AI = A.begin();
47 auto BI = B.begin();
48
49 // Skip default mode, but remember if we had one.
50 bool HasDefault = false;
51 if (AI != A.end() && AI->first == DefaultMode) {
52 HasDefault = true;
53 ++AI;
54 }
55 if (BI != B.end() && BI->first == DefaultMode) {
56 HasDefault = true;
57 ++BI;
58 }
59
60 while (AI != A.end()) {
61 // If we're done with B, finish A.
62 if (BI == B.end()) {
63 for (; AI != A.end(); ++AI)
64 Modes.push_back(AI->first);
65 break;
66 }
67
68 if (BI->first < AI->first) {
69 Modes.push_back(BI->first);
70 ++BI;
71 } else {
72 Modes.push_back(AI->first);
73 if (AI->first == BI->first)
74 ++BI;
75 ++AI;
76 }
77 }
78
79 // Finish B.
80 for (; BI != B.end(); ++BI)
81 Modes.push_back(BI->first);
82
83 // Make sure that the default mode is last on the list.
84 if (HasDefault)
85 Modes.push_back(DefaultMode);
86 }
87
88 template <typename InfoT>
89 struct InfoByHwMode {
90 typedef std::map<unsigned,InfoT> MapType;
91 typedef typename MapType::value_type PairType;
92 typedef typename MapType::iterator iterator;
93 typedef typename MapType::const_iterator const_iterator;
94
95 InfoByHwMode() = default;
InfoByHwModeInfoByHwMode96 InfoByHwMode(const MapType &M) : Map(M) {}
97
98 LLVM_ATTRIBUTE_ALWAYS_INLINE
beginInfoByHwMode99 iterator begin() { return Map.begin(); }
100 LLVM_ATTRIBUTE_ALWAYS_INLINE
endInfoByHwMode101 iterator end() { return Map.end(); }
102 LLVM_ATTRIBUTE_ALWAYS_INLINE
beginInfoByHwMode103 const_iterator begin() const { return Map.begin(); }
104 LLVM_ATTRIBUTE_ALWAYS_INLINE
endInfoByHwMode105 const_iterator end() const { return Map.end(); }
106 LLVM_ATTRIBUTE_ALWAYS_INLINE
emptyInfoByHwMode107 bool empty() const { return Map.empty(); }
108
109 LLVM_ATTRIBUTE_ALWAYS_INLINE
hasModeInfoByHwMode110 bool hasMode(unsigned M) const { return Map.find(M) != Map.end(); }
111 LLVM_ATTRIBUTE_ALWAYS_INLINE
hasDefaultInfoByHwMode112 bool hasDefault() const {
113 return !Map.empty() && Map.begin()->first == DefaultMode;
114 }
115
getInfoByHwMode116 InfoT &get(unsigned Mode) {
117 auto F = Map.find(Mode);
118 if (F != Map.end())
119 return F->second;
120
121 // Copy and insert the default mode which should be first.
122 assert(hasDefault());
123 auto P = Map.insert({Mode, Map.begin()->second});
124 return P.first->second;
125 }
getInfoByHwMode126 const InfoT &get(unsigned Mode) const {
127 auto F = Map.find(Mode);
128 if (F != Map.end())
129 return F->second;
130 // Get the default mode which should be first.
131 F = Map.begin();
132 assert(F != Map.end() && F->first == DefaultMode);
133 return F->second;
134 }
135
136 LLVM_ATTRIBUTE_ALWAYS_INLINE
isSimpleInfoByHwMode137 bool isSimple() const {
138 return Map.size() == 1 && Map.begin()->first == DefaultMode;
139 }
140 LLVM_ATTRIBUTE_ALWAYS_INLINE
getSimpleInfoByHwMode141 const InfoT &getSimple() const {
142 assert(isSimple());
143 return Map.begin()->second;
144 }
makeSimpleInfoByHwMode145 void makeSimple(unsigned Mode) {
146 assert(hasMode(Mode) || hasDefault());
147 InfoT I = get(Mode);
148 Map.clear();
149 Map.insert(std::make_pair(DefaultMode, I));
150 }
151
152 protected:
153 MapType Map;
154 };
155
156 struct ValueTypeByHwMode : public InfoByHwMode<MVT> {
157 ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH);
158 ValueTypeByHwMode(Record *R, MVT T);
ValueTypeByHwModeValueTypeByHwMode159 ValueTypeByHwMode(MVT T) { Map.insert({DefaultMode,T}); }
160 ValueTypeByHwMode() = default;
161
162 bool operator== (const ValueTypeByHwMode &T) const;
163 bool operator< (const ValueTypeByHwMode &T) const;
164
isValidValueTypeByHwMode165 bool isValid() const {
166 return !Map.empty();
167 }
getTypeValueTypeByHwMode168 MVT getType(unsigned Mode) const { return get(Mode); }
169 MVT &getOrCreateTypeForMode(unsigned Mode, MVT Type);
170
171 static StringRef getMVTName(MVT T);
172 void writeToStream(raw_ostream &OS) const;
173 void dump() const;
174
175 unsigned PtrAddrSpace = std::numeric_limits<unsigned>::max();
isPointerValueTypeByHwMode176 bool isPointer() const {
177 return PtrAddrSpace != std::numeric_limits<unsigned>::max();
178 }
179 };
180
181 ValueTypeByHwMode getValueTypeByHwMode(Record *Rec,
182 const CodeGenHwModes &CGH);
183
184 struct RegSizeInfo {
185 unsigned RegSize;
186 unsigned SpillSize;
187 unsigned SpillAlignment;
188
189 RegSizeInfo(Record *R, const CodeGenHwModes &CGH);
190 RegSizeInfo() = default;
191 bool operator< (const RegSizeInfo &I) const;
192 bool operator== (const RegSizeInfo &I) const {
193 return std::tie(RegSize, SpillSize, SpillAlignment) ==
194 std::tie(I.RegSize, I.SpillSize, I.SpillAlignment);
195 }
196 bool operator!= (const RegSizeInfo &I) const {
197 return !(*this == I);
198 }
199
200 bool isSubClassOf(const RegSizeInfo &I) const;
201 void writeToStream(raw_ostream &OS) const;
202 };
203
204 struct RegSizeInfoByHwMode : public InfoByHwMode<RegSizeInfo> {
205 RegSizeInfoByHwMode(Record *R, const CodeGenHwModes &CGH);
206 RegSizeInfoByHwMode() = default;
207 bool operator< (const RegSizeInfoByHwMode &VI) const;
208 bool operator== (const RegSizeInfoByHwMode &VI) const;
209 bool operator!= (const RegSizeInfoByHwMode &VI) const {
210 return !(*this == VI);
211 }
212
213 bool isSubClassOf(const RegSizeInfoByHwMode &I) const;
214 bool hasStricterSpillThan(const RegSizeInfoByHwMode &I) const;
215
216 void writeToStream(raw_ostream &OS) const;
217
insertRegSizeForModeRegSizeInfoByHwMode218 void insertRegSizeForMode(unsigned Mode, RegSizeInfo Info) {
219 Map.insert(std::make_pair(Mode, Info));
220 }
221 };
222
223 raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T);
224 raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T);
225 raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T);
226
227 struct EncodingInfoByHwMode : public InfoByHwMode<Record*> {
228 EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH);
229 EncodingInfoByHwMode() = default;
230 };
231
232 } // namespace llvm
233
234 #endif // LLVM_UTILS_TABLEGEN_INFOBYHWMODE_H
235