1 | //===--- InfoByHwMode.cpp -------------------------------------------------===// |
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 | #include "InfoByHwMode.h" |
15 | #include "CodeGenTarget.h" |
16 | #include "llvm/ADT/STLExtras.h" |
17 | #include "llvm/ADT/Twine.h" |
18 | #include "llvm/Support/Debug.h" |
19 | #include "llvm/Support/raw_ostream.h" |
20 | #include "llvm/TableGen/Record.h" |
21 | #include <string> |
22 | |
23 | using namespace llvm; |
24 | |
25 | std::string llvm::getModeName(unsigned Mode) { |
26 | if (Mode == DefaultMode) |
27 | return "*" ; |
28 | return (Twine('m') + Twine(Mode)).str(); |
29 | } |
30 | |
31 | ValueTypeByHwMode::ValueTypeByHwMode(const Record *R, |
32 | const CodeGenHwModes &CGH) { |
33 | const HwModeSelect &MS = CGH.getHwModeSelect(R); |
34 | for (const HwModeSelect::PairType &P : MS.Items) { |
35 | auto I = Map.try_emplace(k: P.first, args: MVT(llvm::getValueType(Rec: P.second))); |
36 | assert(I.second && "Duplicate entry?" ); |
37 | (void)I; |
38 | } |
39 | if (R->isSubClassOf(Name: "PtrValueType" )) |
40 | PtrAddrSpace = R->getValueAsInt(FieldName: "AddrSpace" ); |
41 | } |
42 | |
43 | ValueTypeByHwMode::ValueTypeByHwMode(const Record *R, MVT T) |
44 | : ValueTypeByHwMode(T) { |
45 | if (R->isSubClassOf(Name: "PtrValueType" )) |
46 | PtrAddrSpace = R->getValueAsInt(FieldName: "AddrSpace" ); |
47 | } |
48 | |
49 | bool ValueTypeByHwMode::operator==(const ValueTypeByHwMode &T) const { |
50 | assert(isValid() && T.isValid() && "Invalid type in assignment" ); |
51 | bool Simple = isSimple(); |
52 | if (Simple != T.isSimple()) |
53 | return false; |
54 | if (Simple) |
55 | return getSimple() == T.getSimple(); |
56 | |
57 | return Map == T.Map; |
58 | } |
59 | |
60 | bool ValueTypeByHwMode::operator<(const ValueTypeByHwMode &T) const { |
61 | assert(isValid() && T.isValid() && "Invalid type in comparison" ); |
62 | // Default order for maps. |
63 | return Map < T.Map; |
64 | } |
65 | |
66 | MVT &ValueTypeByHwMode::getOrCreateTypeForMode(unsigned Mode, MVT Type) { |
67 | auto F = Map.find(x: Mode); |
68 | if (F != Map.end()) |
69 | return F->second; |
70 | // If Mode is not in the map, look up the default mode. If it exists, |
71 | // make a copy of it for Mode and return it. |
72 | auto D = Map.begin(); |
73 | if (D != Map.end() && D->first == DefaultMode) |
74 | return Map.try_emplace(k: Mode, args&: D->second).first->second; |
75 | // If default mode is not present either, use provided Type. |
76 | return Map.try_emplace(k: Mode, args&: Type).first->second; |
77 | } |
78 | |
79 | StringRef ValueTypeByHwMode::getMVTName(MVT T) { |
80 | StringRef N = llvm::getEnumName(T: T.SimpleTy); |
81 | N.consume_front(Prefix: "MVT::" ); |
82 | return N; |
83 | } |
84 | |
85 | void ValueTypeByHwMode::writeToStream(raw_ostream &OS) const { |
86 | if (isSimple()) { |
87 | OS << getMVTName(T: getSimple()); |
88 | return; |
89 | } |
90 | |
91 | std::vector<const PairType *> Pairs; |
92 | for (const auto &P : Map) |
93 | Pairs.push_back(x: &P); |
94 | llvm::sort(C&: Pairs, Comp: deref<std::less<PairType>>()); |
95 | |
96 | OS << '{'; |
97 | ListSeparator LS("," ); |
98 | for (const PairType *P : Pairs) |
99 | OS << LS << '(' << getModeName(Mode: P->first) << ':' |
100 | << getMVTName(T: P->second).str() << ')'; |
101 | OS << '}'; |
102 | } |
103 | |
104 | LLVM_DUMP_METHOD |
105 | void ValueTypeByHwMode::dump() const { dbgs() << *this << '\n'; } |
106 | |
107 | ValueTypeByHwMode llvm::getValueTypeByHwMode(const Record *Rec, |
108 | const CodeGenHwModes &CGH) { |
109 | #ifndef NDEBUG |
110 | if (!Rec->isSubClassOf("ValueType" )) |
111 | Rec->dump(); |
112 | #endif |
113 | assert(Rec->isSubClassOf("ValueType" ) && |
114 | "Record must be derived from ValueType" ); |
115 | if (Rec->isSubClassOf(Name: "HwModeSelect" )) |
116 | return ValueTypeByHwMode(Rec, CGH); |
117 | return ValueTypeByHwMode(Rec, llvm::getValueType(Rec)); |
118 | } |
119 | |
120 | RegSizeInfo::RegSizeInfo(const Record *R) { |
121 | RegSize = R->getValueAsInt(FieldName: "RegSize" ); |
122 | SpillSize = R->getValueAsInt(FieldName: "SpillSize" ); |
123 | SpillAlignment = R->getValueAsInt(FieldName: "SpillAlignment" ); |
124 | } |
125 | |
126 | bool RegSizeInfo::operator<(const RegSizeInfo &I) const { |
127 | return std::tie(args: RegSize, args: SpillSize, args: SpillAlignment) < |
128 | std::tie(args: I.RegSize, args: I.SpillSize, args: I.SpillAlignment); |
129 | } |
130 | |
131 | bool RegSizeInfo::isSubClassOf(const RegSizeInfo &I) const { |
132 | return RegSize <= I.RegSize && SpillAlignment && |
133 | I.SpillAlignment % SpillAlignment == 0 && SpillSize <= I.SpillSize; |
134 | } |
135 | |
136 | void RegSizeInfo::writeToStream(raw_ostream &OS) const { |
137 | OS << "[R=" << RegSize << ",S=" << SpillSize << ",A=" << SpillAlignment |
138 | << ']'; |
139 | } |
140 | |
141 | RegSizeInfoByHwMode::RegSizeInfoByHwMode(const Record *R, |
142 | const CodeGenHwModes &CGH) { |
143 | const HwModeSelect &MS = CGH.getHwModeSelect(R); |
144 | for (const HwModeSelect::PairType &P : MS.Items) { |
145 | auto I = Map.try_emplace(k: P.first, args: RegSizeInfo(P.second)); |
146 | assert(I.second && "Duplicate entry?" ); |
147 | (void)I; |
148 | } |
149 | } |
150 | |
151 | bool RegSizeInfoByHwMode::operator<(const RegSizeInfoByHwMode &I) const { |
152 | unsigned M0 = Map.begin()->first; |
153 | return get(Mode: M0) < I.get(Mode: M0); |
154 | } |
155 | |
156 | bool RegSizeInfoByHwMode::operator==(const RegSizeInfoByHwMode &I) const { |
157 | unsigned M0 = Map.begin()->first; |
158 | return get(Mode: M0) == I.get(Mode: M0); |
159 | } |
160 | |
161 | bool RegSizeInfoByHwMode::isSubClassOf(const RegSizeInfoByHwMode &I) const { |
162 | unsigned M0 = Map.begin()->first; |
163 | return get(Mode: M0).isSubClassOf(I: I.get(Mode: M0)); |
164 | } |
165 | |
166 | bool RegSizeInfoByHwMode::hasStricterSpillThan( |
167 | const RegSizeInfoByHwMode &I) const { |
168 | unsigned M0 = Map.begin()->first; |
169 | const RegSizeInfo &A0 = get(Mode: M0); |
170 | const RegSizeInfo &B0 = I.get(Mode: M0); |
171 | return std::tie(args: A0.SpillSize, args: A0.SpillAlignment) > |
172 | std::tie(args: B0.SpillSize, args: B0.SpillAlignment); |
173 | } |
174 | |
175 | void RegSizeInfoByHwMode::writeToStream(raw_ostream &OS) const { |
176 | typedef typename decltype(Map)::value_type PairType; |
177 | std::vector<const PairType *> Pairs; |
178 | for (const auto &P : Map) |
179 | Pairs.push_back(x: &P); |
180 | llvm::sort(C&: Pairs, Comp: deref<std::less<PairType>>()); |
181 | |
182 | OS << '{'; |
183 | ListSeparator LS("," ); |
184 | for (const PairType *P : Pairs) |
185 | OS << LS << '(' << getModeName(Mode: P->first) << ':' << P->second << ')'; |
186 | OS << '}'; |
187 | } |
188 | |
189 | SubRegRange::SubRegRange(const Record *R) { |
190 | Size = R->getValueAsInt(FieldName: "Size" ); |
191 | Offset = R->getValueAsInt(FieldName: "Offset" ); |
192 | } |
193 | |
194 | SubRegRangeByHwMode::SubRegRangeByHwMode(const Record *R, |
195 | const CodeGenHwModes &CGH) { |
196 | const HwModeSelect &MS = CGH.getHwModeSelect(R); |
197 | for (const HwModeSelect::PairType &P : MS.Items) { |
198 | auto I = Map.try_emplace(k: P.first, args: SubRegRange(P.second)); |
199 | assert(I.second && "Duplicate entry?" ); |
200 | (void)I; |
201 | } |
202 | } |
203 | |
204 | EncodingInfoByHwMode::EncodingInfoByHwMode(const Record *R, |
205 | const CodeGenHwModes &CGH) { |
206 | const HwModeSelect &MS = CGH.getHwModeSelect(R); |
207 | for (const HwModeSelect::PairType &P : MS.Items) { |
208 | assert(P.second && P.second->isSubClassOf("InstructionEncoding" ) && |
209 | "Encoding must subclass InstructionEncoding" ); |
210 | auto I = Map.try_emplace(k: P.first, args: P.second); |
211 | assert(I.second && "Duplicate entry?" ); |
212 | (void)I; |
213 | } |
214 | } |
215 | |
216 | namespace llvm { |
217 | raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T) { |
218 | T.writeToStream(OS); |
219 | return OS; |
220 | } |
221 | |
222 | raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T) { |
223 | T.writeToStream(OS); |
224 | return OS; |
225 | } |
226 | |
227 | raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T) { |
228 | T.writeToStream(OS); |
229 | return OS; |
230 | } |
231 | } // namespace llvm |
232 | |