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 29namespace llvm { 30 31class Record; 32class raw_ostream; 33 34template <typename InfoT> struct InfoByHwMode; 35 36std::string getModeName(unsigned Mode); 37 38enum : unsigned { 39 DefaultMode = CodeGenHwModes::DefaultMode, 40}; 41 42template <typename InfoT> 43void 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 88template <typename InfoT> 89struct 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; 96 InfoByHwMode(const MapType &M) : Map(M) {} 97 98 LLVM_ATTRIBUTE_ALWAYS_INLINE 99 iterator begin() { return Map.begin(); } 100 LLVM_ATTRIBUTE_ALWAYS_INLINE 101 iterator end() { return Map.end(); } 102 LLVM_ATTRIBUTE_ALWAYS_INLINE 103 const_iterator begin() const { return Map.begin(); } 104 LLVM_ATTRIBUTE_ALWAYS_INLINE 105 const_iterator end() const { return Map.end(); } 106 LLVM_ATTRIBUTE_ALWAYS_INLINE 107 bool empty() const { return Map.empty(); } 108 109 LLVM_ATTRIBUTE_ALWAYS_INLINE 110 bool hasMode(unsigned M) const { return Map.find(M) != Map.end(); } 111 LLVM_ATTRIBUTE_ALWAYS_INLINE 112 bool hasDefault() const { 113 return !Map.empty() && Map.begin()->first == DefaultMode; 114 } 115 116 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 } 126 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 137 bool isSimple() const { 138 return Map.size() == 1 && Map.begin()->first == DefaultMode; 139 } 140 LLVM_ATTRIBUTE_ALWAYS_INLINE 141 const InfoT &getSimple() const { 142 assert(isSimple()); 143 return Map.begin()->second; 144 } 145 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 152protected: 153 MapType Map; 154}; 155 156struct ValueTypeByHwMode : public InfoByHwMode<MVT> { 157 ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH); 158 ValueTypeByHwMode(Record *R, MVT T); 159 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 165 bool isValid() const { 166 return !Map.empty(); 167 } 168 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(); 176 bool isPointer() const { 177 return PtrAddrSpace != std::numeric_limits<unsigned>::max(); 178 } 179}; 180 181ValueTypeByHwMode getValueTypeByHwMode(Record *Rec, 182 const CodeGenHwModes &CGH); 183 184struct 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 204struct 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 218 void insertRegSizeForMode(unsigned Mode, RegSizeInfo Info) { 219 Map.insert(std::make_pair(Mode, Info)); 220 } 221}; 222 223raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T); 224raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T); 225raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T); 226 227struct 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