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