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