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