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