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