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/CodeGen/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 
29 namespace llvm {
30 
31 class Record;
32 class raw_ostream;
33 
34 template <typename InfoT> struct InfoByHwMode;
35 
36 std::string getModeName(unsigned Mode);
37 
38 enum : unsigned {
39   DefaultMode = CodeGenHwModes::DefaultMode,
40 };
41 
42 template <typename InfoT>
union_modes(const InfoByHwMode<InfoT> & A,const InfoByHwMode<InfoT> & B,SmallVectorImpl<unsigned> & Modes)43 void union_modes(const InfoByHwMode<InfoT> &A,
44                  const InfoByHwMode<InfoT> &B,
45                  SmallVectorImpl<unsigned> &Modes) {
46   auto AI = A.begin();
47   auto BI = B.begin();
48 
49   // Skip default mode, but remember if we had one.
50   bool HasDefault = false;
51   if (AI != A.end() && AI->first == DefaultMode) {
52     HasDefault = true;
53     ++AI;
54   }
55   if (BI != B.end() && BI->first == DefaultMode) {
56     HasDefault = true;
57     ++BI;
58   }
59 
60   while (AI != A.end()) {
61     // If we're done with B, finish A.
62     if (BI == B.end()) {
63       for (; AI != A.end(); ++AI)
64         Modes.push_back(AI->first);
65       break;
66     }
67 
68     if (BI->first < AI->first) {
69       Modes.push_back(BI->first);
70       ++BI;
71     } else {
72       Modes.push_back(AI->first);
73       if (AI->first == BI->first)
74         ++BI;
75       ++AI;
76     }
77   }
78 
79   // Finish B.
80   for (; BI != B.end(); ++BI)
81     Modes.push_back(BI->first);
82 
83   // Make sure that the default mode is last on the list.
84   if (HasDefault)
85     Modes.push_back(DefaultMode);
86 }
87 
88 template <typename InfoT>
89 struct InfoByHwMode {
90   typedef std::map<unsigned,InfoT> MapType;
91   typedef typename MapType::value_type PairType;
92   typedef typename MapType::iterator iterator;
93   typedef typename MapType::const_iterator const_iterator;
94 
95   InfoByHwMode() = default;
InfoByHwModeInfoByHwMode96   InfoByHwMode(const MapType &M) : Map(M) {}
97 
98   LLVM_ATTRIBUTE_ALWAYS_INLINE
beginInfoByHwMode99   iterator begin() { return Map.begin(); }
100   LLVM_ATTRIBUTE_ALWAYS_INLINE
endInfoByHwMode101   iterator end()   { return Map.end(); }
102   LLVM_ATTRIBUTE_ALWAYS_INLINE
beginInfoByHwMode103   const_iterator begin() const { return Map.begin(); }
104   LLVM_ATTRIBUTE_ALWAYS_INLINE
endInfoByHwMode105   const_iterator end() const   { return Map.end(); }
106   LLVM_ATTRIBUTE_ALWAYS_INLINE
emptyInfoByHwMode107   bool empty() const { return Map.empty(); }
108 
109   LLVM_ATTRIBUTE_ALWAYS_INLINE
hasModeInfoByHwMode110   bool hasMode(unsigned M) const { return Map.find(M) != Map.end(); }
111   LLVM_ATTRIBUTE_ALWAYS_INLINE
hasDefaultInfoByHwMode112   bool hasDefault() const {
113     return !Map.empty() && Map.begin()->first == DefaultMode;
114   }
115 
getInfoByHwMode116   InfoT &get(unsigned Mode) {
117     auto F = Map.find(Mode);
118     if (F != Map.end())
119       return F->second;
120 
121     // Copy and insert the default mode which should be first.
122     assert(hasDefault());
123     auto P = Map.insert({Mode, Map.begin()->second});
124     return P.first->second;
125   }
getInfoByHwMode126   const InfoT &get(unsigned Mode) const {
127     auto F = Map.find(Mode);
128     if (F != Map.end())
129       return F->second;
130     // Get the default mode which should be first.
131     F = Map.begin();
132     assert(F != Map.end() && F->first == DefaultMode);
133     return F->second;
134   }
135 
136   LLVM_ATTRIBUTE_ALWAYS_INLINE
isSimpleInfoByHwMode137   bool isSimple() const {
138     return Map.size() == 1 && Map.begin()->first == DefaultMode;
139   }
140   LLVM_ATTRIBUTE_ALWAYS_INLINE
getSimpleInfoByHwMode141   const InfoT &getSimple() const {
142     assert(isSimple());
143     return Map.begin()->second;
144   }
makeSimpleInfoByHwMode145   void makeSimple(unsigned Mode) {
146     assert(hasMode(Mode) || hasDefault());
147     InfoT I = get(Mode);
148     Map.clear();
149     Map.insert(std::make_pair(DefaultMode, I));
150   }
151 
152 protected:
153   MapType Map;
154 };
155 
156 struct ValueTypeByHwMode : public InfoByHwMode<MVT> {
157   ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH);
158   ValueTypeByHwMode(Record *R, MVT T);
ValueTypeByHwModeValueTypeByHwMode159   ValueTypeByHwMode(MVT T) { Map.insert({DefaultMode,T}); }
160   ValueTypeByHwMode() = default;
161 
162   bool operator== (const ValueTypeByHwMode &T) const;
163   bool operator< (const ValueTypeByHwMode &T) const;
164 
isValidValueTypeByHwMode165   bool isValid() const {
166     return !Map.empty();
167   }
getTypeValueTypeByHwMode168   MVT getType(unsigned Mode) const { return get(Mode); }
169   MVT &getOrCreateTypeForMode(unsigned Mode, MVT Type);
170 
171   static StringRef getMVTName(MVT T);
172   void writeToStream(raw_ostream &OS) const;
173   void dump() const;
174 
175   unsigned PtrAddrSpace = std::numeric_limits<unsigned>::max();
isPointerValueTypeByHwMode176   bool isPointer() const {
177     return PtrAddrSpace != std::numeric_limits<unsigned>::max();
178   }
179 };
180 
181 ValueTypeByHwMode getValueTypeByHwMode(Record *Rec,
182                                        const CodeGenHwModes &CGH);
183 
184 struct RegSizeInfo {
185   unsigned RegSize;
186   unsigned SpillSize;
187   unsigned SpillAlignment;
188 
189   RegSizeInfo(Record *R, const CodeGenHwModes &CGH);
190   RegSizeInfo() = default;
191   bool operator< (const RegSizeInfo &I) const;
192   bool operator== (const RegSizeInfo &I) const {
193     return std::tie(RegSize, SpillSize, SpillAlignment) ==
194            std::tie(I.RegSize, I.SpillSize, I.SpillAlignment);
195   }
196   bool operator!= (const RegSizeInfo &I) const {
197     return !(*this == I);
198   }
199 
200   bool isSubClassOf(const RegSizeInfo &I) const;
201   void writeToStream(raw_ostream &OS) const;
202 };
203 
204 struct RegSizeInfoByHwMode : public InfoByHwMode<RegSizeInfo> {
205   RegSizeInfoByHwMode(Record *R, const CodeGenHwModes &CGH);
206   RegSizeInfoByHwMode() = default;
207   bool operator< (const RegSizeInfoByHwMode &VI) const;
208   bool operator== (const RegSizeInfoByHwMode &VI) const;
209   bool operator!= (const RegSizeInfoByHwMode &VI) const {
210     return !(*this == VI);
211   }
212 
213   bool isSubClassOf(const RegSizeInfoByHwMode &I) const;
214   bool hasStricterSpillThan(const RegSizeInfoByHwMode &I) const;
215 
216   void writeToStream(raw_ostream &OS) const;
217 
insertRegSizeForModeRegSizeInfoByHwMode218   void insertRegSizeForMode(unsigned Mode, RegSizeInfo Info) {
219     Map.insert(std::make_pair(Mode, Info));
220   }
221 };
222 
223 raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T);
224 raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T);
225 raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T);
226 
227 struct EncodingInfoByHwMode : public InfoByHwMode<Record*> {
228   EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH);
229   EncodingInfoByHwMode() = default;
230 };
231 
232 } // namespace llvm
233 
234 #endif // LLVM_UTILS_TABLEGEN_INFOBYHWMODE_H
235