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
29namespace llvm {
30
31class Record;
32class raw_ostream;
33
34template <typename InfoT> struct InfoByHwMode;
35
36std::string getModeName(unsigned Mode);
37
38enum : unsigned {
39 DefaultMode = CodeGenHwModes::DefaultMode,
40};
41
42template <typename InfoT>
43void 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
87template <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
150protected:
151 MapType Map;
152};
153
154struct 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
177ValueTypeByHwMode getValueTypeByHwMode(Record *Rec, const CodeGenHwModes &CGH);
178
179raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T);
180
181struct 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
199struct 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
218raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T);
219raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T);
220
221struct 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
229struct 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
239struct 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