260 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8// Classes that implement data parameterized by HW modes for instruction9// selection. Currently it is ValueTypeByHwMode (parameterized ValueType),10// and RegSizeInfoByHwMode (parameterized register/spill size and alignment11// data).12//===----------------------------------------------------------------------===//13 14#ifndef LLVM_UTILS_TABLEGEN_COMMON_INFOBYHWMODE_H15#define LLVM_UTILS_TABLEGEN_COMMON_INFOBYHWMODE_H16 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 28namespace llvm {29 30class CodeGenRegBank;31class CodeGenRegisterClass;32class Record;33class raw_ostream;34 35template <typename InfoT> struct InfoByHwMode;36 37std::string getModeName(unsigned Mode);38 39enum : unsigned {40 DefaultMode = CodeGenHwModes::DefaultMode,41};42 43template <typename InfoT>44void union_modes(const InfoByHwMode<InfoT> &A, 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> struct InfoByHwMode {89 using MapType = std::map<unsigned, InfoT>;90 using PairType = typename MapType::value_type;91 using iterator = typename MapType::iterator;92 using const_iterator = typename MapType::const_iterator;93 94 InfoByHwMode() = default;95 InfoByHwMode(const MapType &M) : Map(M) {}96 97 LLVM_ATTRIBUTE_ALWAYS_INLINE98 iterator begin() { return Map.begin(); }99 LLVM_ATTRIBUTE_ALWAYS_INLINE100 iterator end() { return Map.end(); }101 LLVM_ATTRIBUTE_ALWAYS_INLINE102 const_iterator begin() const { return Map.begin(); }103 LLVM_ATTRIBUTE_ALWAYS_INLINE104 const_iterator end() const { return Map.end(); }105 LLVM_ATTRIBUTE_ALWAYS_INLINE106 size_t size() const { return Map.size(); }107 LLVM_ATTRIBUTE_ALWAYS_INLINE108 bool empty() const { return Map.empty(); }109 110 LLVM_ATTRIBUTE_ALWAYS_INLINE111 bool hasMode(unsigned M) const { return Map.find(M) != Map.end(); }112 LLVM_ATTRIBUTE_ALWAYS_INLINE113 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.try_emplace(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_INLINE138 bool isSimple() const {139 return Map.size() == 1 && Map.begin()->first == DefaultMode;140 }141 LLVM_ATTRIBUTE_ALWAYS_INLINE142 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.try_emplace(DefaultMode, I);151 }152 153protected:154 MapType Map;155};156 157struct ValueTypeByHwMode : public InfoByHwMode<MVT> {158 ValueTypeByHwMode(const Record *R, const CodeGenHwModes &CGH);159 ValueTypeByHwMode(const Record *R, MVT T);160 ValueTypeByHwMode(MVT T) { Map.try_emplace(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 { return !Map.empty(); }167 MVT getType(unsigned Mode) const { return get(Mode); }168 MVT &getOrCreateTypeForMode(unsigned Mode, MVT Type);169 170 static StringRef getMVTName(MVT T);171 void writeToStream(raw_ostream &OS) const;172 void dump() const;173 174 unsigned PtrAddrSpace = std::numeric_limits<unsigned>::max();175 bool isPointer() const {176 return PtrAddrSpace != std::numeric_limits<unsigned>::max();177 }178};179 180ValueTypeByHwMode getValueTypeByHwMode(const Record *Rec,181 const CodeGenHwModes &CGH);182 183raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T);184 185struct RegSizeInfo {186 unsigned RegSize;187 unsigned SpillSize;188 unsigned SpillAlignment;189 190 RegSizeInfo(const Record *R);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 { return !(*this == I); }198 199 bool isSubClassOf(const RegSizeInfo &I) const;200 void writeToStream(raw_ostream &OS) const;201};202 203struct RegSizeInfoByHwMode : public InfoByHwMode<RegSizeInfo> {204 RegSizeInfoByHwMode(const Record *R, const CodeGenHwModes &CGH);205 RegSizeInfoByHwMode() = default;206 bool operator<(const RegSizeInfoByHwMode &VI) const;207 bool operator==(const RegSizeInfoByHwMode &VI) const;208 bool operator!=(const RegSizeInfoByHwMode &VI) const {209 return !(*this == VI);210 }211 212 bool isSubClassOf(const RegSizeInfoByHwMode &I) const;213 bool hasStricterSpillThan(const RegSizeInfoByHwMode &I) const;214 215 void writeToStream(raw_ostream &OS) const;216 217 void insertRegSizeForMode(unsigned Mode, RegSizeInfo Info) {218 Map.try_emplace(Mode, Info);219 }220};221 222raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T);223raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T);224 225struct SubRegRange {226 uint16_t Size;227 uint16_t Offset;228 229 SubRegRange(const Record *R);230 SubRegRange(uint16_t Size, uint16_t Offset) : Size(Size), Offset(Offset) {}231};232 233struct SubRegRangeByHwMode : public InfoByHwMode<SubRegRange> {234 SubRegRangeByHwMode(const Record *R, const CodeGenHwModes &CGH);235 SubRegRangeByHwMode(SubRegRange Range) {236 Map.try_emplace(DefaultMode, Range);237 }238 SubRegRangeByHwMode() = default;239 240 void insertSubRegRangeForMode(unsigned Mode, SubRegRange Info) {241 Map.try_emplace(Mode, Info);242 }243};244 245struct EncodingInfoByHwMode : public InfoByHwMode<const Record *> {246 EncodingInfoByHwMode(const Record *R, const CodeGenHwModes &CGH);247 EncodingInfoByHwMode() = default;248};249 250struct RegClassByHwMode : public InfoByHwMode<const CodeGenRegisterClass *> {251public:252 RegClassByHwMode(const Record *R, const CodeGenHwModes &CGH,253 const CodeGenRegBank &RegBank);254 RegClassByHwMode() = default;255};256 257} // namespace llvm258 259#endif // LLVM_UTILS_TABLEGEN_COMMON_INFOBYHWMODE_H260