1*0fca6ea1SDimitry Andric //===--- InfoByHwMode.h -----------------------------------------*- C++ -*-===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric // Classes that implement data parameterized by HW modes for instruction
9*0fca6ea1SDimitry Andric // selection. Currently it is ValueTypeByHwMode (parameterized ValueType),
10*0fca6ea1SDimitry Andric // and RegSizeInfoByHwMode (parameterized register/spill size and alignment
11*0fca6ea1SDimitry Andric // data).
12*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
13*0fca6ea1SDimitry Andric
14*0fca6ea1SDimitry Andric #ifndef LLVM_UTILS_TABLEGEN_INFOBYHWMODE_H
15*0fca6ea1SDimitry Andric #define LLVM_UTILS_TABLEGEN_INFOBYHWMODE_H
16*0fca6ea1SDimitry Andric
17*0fca6ea1SDimitry Andric #include "CodeGenHwModes.h"
18*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallVector.h"
19*0fca6ea1SDimitry Andric #include "llvm/ADT/StringRef.h"
20*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h"
21*0fca6ea1SDimitry Andric #include "llvm/Support/Compiler.h"
22*0fca6ea1SDimitry Andric #include <cassert>
23*0fca6ea1SDimitry Andric #include <limits>
24*0fca6ea1SDimitry Andric #include <map>
25*0fca6ea1SDimitry Andric #include <string>
26*0fca6ea1SDimitry Andric #include <tuple>
27*0fca6ea1SDimitry Andric #include <utility>
28*0fca6ea1SDimitry Andric
29*0fca6ea1SDimitry Andric namespace llvm {
30*0fca6ea1SDimitry Andric
31*0fca6ea1SDimitry Andric class Record;
32*0fca6ea1SDimitry Andric class raw_ostream;
33*0fca6ea1SDimitry Andric
34*0fca6ea1SDimitry Andric template <typename InfoT> struct InfoByHwMode;
35*0fca6ea1SDimitry Andric
36*0fca6ea1SDimitry Andric std::string getModeName(unsigned Mode);
37*0fca6ea1SDimitry Andric
38*0fca6ea1SDimitry Andric enum : unsigned {
39*0fca6ea1SDimitry Andric DefaultMode = CodeGenHwModes::DefaultMode,
40*0fca6ea1SDimitry Andric };
41*0fca6ea1SDimitry Andric
42*0fca6ea1SDimitry Andric template <typename InfoT>
union_modes(const InfoByHwMode<InfoT> & A,const InfoByHwMode<InfoT> & B,SmallVectorImpl<unsigned> & Modes)43*0fca6ea1SDimitry Andric void union_modes(const InfoByHwMode<InfoT> &A, const InfoByHwMode<InfoT> &B,
44*0fca6ea1SDimitry Andric SmallVectorImpl<unsigned> &Modes) {
45*0fca6ea1SDimitry Andric auto AI = A.begin();
46*0fca6ea1SDimitry Andric auto BI = B.begin();
47*0fca6ea1SDimitry Andric
48*0fca6ea1SDimitry Andric // Skip default mode, but remember if we had one.
49*0fca6ea1SDimitry Andric bool HasDefault = false;
50*0fca6ea1SDimitry Andric if (AI != A.end() && AI->first == DefaultMode) {
51*0fca6ea1SDimitry Andric HasDefault = true;
52*0fca6ea1SDimitry Andric ++AI;
53*0fca6ea1SDimitry Andric }
54*0fca6ea1SDimitry Andric if (BI != B.end() && BI->first == DefaultMode) {
55*0fca6ea1SDimitry Andric HasDefault = true;
56*0fca6ea1SDimitry Andric ++BI;
57*0fca6ea1SDimitry Andric }
58*0fca6ea1SDimitry Andric
59*0fca6ea1SDimitry Andric while (AI != A.end()) {
60*0fca6ea1SDimitry Andric // If we're done with B, finish A.
61*0fca6ea1SDimitry Andric if (BI == B.end()) {
62*0fca6ea1SDimitry Andric for (; AI != A.end(); ++AI)
63*0fca6ea1SDimitry Andric Modes.push_back(AI->first);
64*0fca6ea1SDimitry Andric break;
65*0fca6ea1SDimitry Andric }
66*0fca6ea1SDimitry Andric
67*0fca6ea1SDimitry Andric if (BI->first < AI->first) {
68*0fca6ea1SDimitry Andric Modes.push_back(BI->first);
69*0fca6ea1SDimitry Andric ++BI;
70*0fca6ea1SDimitry Andric } else {
71*0fca6ea1SDimitry Andric Modes.push_back(AI->first);
72*0fca6ea1SDimitry Andric if (AI->first == BI->first)
73*0fca6ea1SDimitry Andric ++BI;
74*0fca6ea1SDimitry Andric ++AI;
75*0fca6ea1SDimitry Andric }
76*0fca6ea1SDimitry Andric }
77*0fca6ea1SDimitry Andric
78*0fca6ea1SDimitry Andric // Finish B.
79*0fca6ea1SDimitry Andric for (; BI != B.end(); ++BI)
80*0fca6ea1SDimitry Andric Modes.push_back(BI->first);
81*0fca6ea1SDimitry Andric
82*0fca6ea1SDimitry Andric // Make sure that the default mode is last on the list.
83*0fca6ea1SDimitry Andric if (HasDefault)
84*0fca6ea1SDimitry Andric Modes.push_back(DefaultMode);
85*0fca6ea1SDimitry Andric }
86*0fca6ea1SDimitry Andric
87*0fca6ea1SDimitry Andric template <typename InfoT> struct InfoByHwMode {
88*0fca6ea1SDimitry Andric typedef std::map<unsigned, InfoT> MapType;
89*0fca6ea1SDimitry Andric typedef typename MapType::value_type PairType;
90*0fca6ea1SDimitry Andric typedef typename MapType::iterator iterator;
91*0fca6ea1SDimitry Andric typedef typename MapType::const_iterator const_iterator;
92*0fca6ea1SDimitry Andric
93*0fca6ea1SDimitry Andric InfoByHwMode() = default;
InfoByHwModeInfoByHwMode94*0fca6ea1SDimitry Andric InfoByHwMode(const MapType &M) : Map(M) {}
95*0fca6ea1SDimitry Andric
96*0fca6ea1SDimitry Andric LLVM_ATTRIBUTE_ALWAYS_INLINE
beginInfoByHwMode97*0fca6ea1SDimitry Andric iterator begin() { return Map.begin(); }
98*0fca6ea1SDimitry Andric LLVM_ATTRIBUTE_ALWAYS_INLINE
endInfoByHwMode99*0fca6ea1SDimitry Andric iterator end() { return Map.end(); }
100*0fca6ea1SDimitry Andric LLVM_ATTRIBUTE_ALWAYS_INLINE
beginInfoByHwMode101*0fca6ea1SDimitry Andric const_iterator begin() const { return Map.begin(); }
102*0fca6ea1SDimitry Andric LLVM_ATTRIBUTE_ALWAYS_INLINE
endInfoByHwMode103*0fca6ea1SDimitry Andric const_iterator end() const { return Map.end(); }
104*0fca6ea1SDimitry Andric LLVM_ATTRIBUTE_ALWAYS_INLINE
emptyInfoByHwMode105*0fca6ea1SDimitry Andric bool empty() const { return Map.empty(); }
106*0fca6ea1SDimitry Andric
107*0fca6ea1SDimitry Andric LLVM_ATTRIBUTE_ALWAYS_INLINE
hasModeInfoByHwMode108*0fca6ea1SDimitry Andric bool hasMode(unsigned M) const { return Map.find(M) != Map.end(); }
109*0fca6ea1SDimitry Andric LLVM_ATTRIBUTE_ALWAYS_INLINE
hasDefaultInfoByHwMode110*0fca6ea1SDimitry Andric bool hasDefault() const {
111*0fca6ea1SDimitry Andric return !Map.empty() && Map.begin()->first == DefaultMode;
112*0fca6ea1SDimitry Andric }
113*0fca6ea1SDimitry Andric
getInfoByHwMode114*0fca6ea1SDimitry Andric InfoT &get(unsigned Mode) {
115*0fca6ea1SDimitry Andric auto F = Map.find(Mode);
116*0fca6ea1SDimitry Andric if (F != Map.end())
117*0fca6ea1SDimitry Andric return F->second;
118*0fca6ea1SDimitry Andric
119*0fca6ea1SDimitry Andric // Copy and insert the default mode which should be first.
120*0fca6ea1SDimitry Andric assert(hasDefault());
121*0fca6ea1SDimitry Andric auto P = Map.insert({Mode, Map.begin()->second});
122*0fca6ea1SDimitry Andric return P.first->second;
123*0fca6ea1SDimitry Andric }
getInfoByHwMode124*0fca6ea1SDimitry Andric const InfoT &get(unsigned Mode) const {
125*0fca6ea1SDimitry Andric auto F = Map.find(Mode);
126*0fca6ea1SDimitry Andric if (F != Map.end())
127*0fca6ea1SDimitry Andric return F->second;
128*0fca6ea1SDimitry Andric // Get the default mode which should be first.
129*0fca6ea1SDimitry Andric F = Map.begin();
130*0fca6ea1SDimitry Andric assert(F != Map.end() && F->first == DefaultMode);
131*0fca6ea1SDimitry Andric return F->second;
132*0fca6ea1SDimitry Andric }
133*0fca6ea1SDimitry Andric
134*0fca6ea1SDimitry Andric LLVM_ATTRIBUTE_ALWAYS_INLINE
isSimpleInfoByHwMode135*0fca6ea1SDimitry Andric bool isSimple() const {
136*0fca6ea1SDimitry Andric return Map.size() == 1 && Map.begin()->first == DefaultMode;
137*0fca6ea1SDimitry Andric }
138*0fca6ea1SDimitry Andric LLVM_ATTRIBUTE_ALWAYS_INLINE
getSimpleInfoByHwMode139*0fca6ea1SDimitry Andric const InfoT &getSimple() const {
140*0fca6ea1SDimitry Andric assert(isSimple());
141*0fca6ea1SDimitry Andric return Map.begin()->second;
142*0fca6ea1SDimitry Andric }
makeSimpleInfoByHwMode143*0fca6ea1SDimitry Andric void makeSimple(unsigned Mode) {
144*0fca6ea1SDimitry Andric assert(hasMode(Mode) || hasDefault());
145*0fca6ea1SDimitry Andric InfoT I = get(Mode);
146*0fca6ea1SDimitry Andric Map.clear();
147*0fca6ea1SDimitry Andric Map.insert(std::pair(DefaultMode, I));
148*0fca6ea1SDimitry Andric }
149*0fca6ea1SDimitry Andric
150*0fca6ea1SDimitry Andric protected:
151*0fca6ea1SDimitry Andric MapType Map;
152*0fca6ea1SDimitry Andric };
153*0fca6ea1SDimitry Andric
154*0fca6ea1SDimitry Andric struct ValueTypeByHwMode : public InfoByHwMode<MVT> {
155*0fca6ea1SDimitry Andric ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH);
156*0fca6ea1SDimitry Andric ValueTypeByHwMode(Record *R, MVT T);
ValueTypeByHwModeValueTypeByHwMode157*0fca6ea1SDimitry Andric ValueTypeByHwMode(MVT T) { Map.insert({DefaultMode, T}); }
158*0fca6ea1SDimitry Andric ValueTypeByHwMode() = default;
159*0fca6ea1SDimitry Andric
160*0fca6ea1SDimitry Andric bool operator==(const ValueTypeByHwMode &T) const;
161*0fca6ea1SDimitry Andric bool operator<(const ValueTypeByHwMode &T) const;
162*0fca6ea1SDimitry Andric
isValidValueTypeByHwMode163*0fca6ea1SDimitry Andric bool isValid() const { return !Map.empty(); }
getTypeValueTypeByHwMode164*0fca6ea1SDimitry Andric MVT getType(unsigned Mode) const { return get(Mode); }
165*0fca6ea1SDimitry Andric MVT &getOrCreateTypeForMode(unsigned Mode, MVT Type);
166*0fca6ea1SDimitry Andric
167*0fca6ea1SDimitry Andric static StringRef getMVTName(MVT T);
168*0fca6ea1SDimitry Andric void writeToStream(raw_ostream &OS) const;
169*0fca6ea1SDimitry Andric void dump() const;
170*0fca6ea1SDimitry Andric
171*0fca6ea1SDimitry Andric unsigned PtrAddrSpace = std::numeric_limits<unsigned>::max();
isPointerValueTypeByHwMode172*0fca6ea1SDimitry Andric bool isPointer() const {
173*0fca6ea1SDimitry Andric return PtrAddrSpace != std::numeric_limits<unsigned>::max();
174*0fca6ea1SDimitry Andric }
175*0fca6ea1SDimitry Andric };
176*0fca6ea1SDimitry Andric
177*0fca6ea1SDimitry Andric ValueTypeByHwMode getValueTypeByHwMode(Record *Rec, const CodeGenHwModes &CGH);
178*0fca6ea1SDimitry Andric
179*0fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T);
180*0fca6ea1SDimitry Andric
181*0fca6ea1SDimitry Andric struct RegSizeInfo {
182*0fca6ea1SDimitry Andric unsigned RegSize;
183*0fca6ea1SDimitry Andric unsigned SpillSize;
184*0fca6ea1SDimitry Andric unsigned SpillAlignment;
185*0fca6ea1SDimitry Andric
186*0fca6ea1SDimitry Andric RegSizeInfo(Record *R);
187*0fca6ea1SDimitry Andric RegSizeInfo() = default;
188*0fca6ea1SDimitry Andric bool operator<(const RegSizeInfo &I) const;
189*0fca6ea1SDimitry Andric bool operator==(const RegSizeInfo &I) const {
190*0fca6ea1SDimitry Andric return std::tie(RegSize, SpillSize, SpillAlignment) ==
191*0fca6ea1SDimitry Andric std::tie(I.RegSize, I.SpillSize, I.SpillAlignment);
192*0fca6ea1SDimitry Andric }
193*0fca6ea1SDimitry Andric bool operator!=(const RegSizeInfo &I) const { return !(*this == I); }
194*0fca6ea1SDimitry Andric
195*0fca6ea1SDimitry Andric bool isSubClassOf(const RegSizeInfo &I) const;
196*0fca6ea1SDimitry Andric void writeToStream(raw_ostream &OS) const;
197*0fca6ea1SDimitry Andric };
198*0fca6ea1SDimitry Andric
199*0fca6ea1SDimitry Andric struct RegSizeInfoByHwMode : public InfoByHwMode<RegSizeInfo> {
200*0fca6ea1SDimitry Andric RegSizeInfoByHwMode(Record *R, const CodeGenHwModes &CGH);
201*0fca6ea1SDimitry Andric RegSizeInfoByHwMode() = default;
202*0fca6ea1SDimitry Andric bool operator<(const RegSizeInfoByHwMode &VI) const;
203*0fca6ea1SDimitry Andric bool operator==(const RegSizeInfoByHwMode &VI) const;
204*0fca6ea1SDimitry Andric bool operator!=(const RegSizeInfoByHwMode &VI) const {
205*0fca6ea1SDimitry Andric return !(*this == VI);
206*0fca6ea1SDimitry Andric }
207*0fca6ea1SDimitry Andric
208*0fca6ea1SDimitry Andric bool isSubClassOf(const RegSizeInfoByHwMode &I) const;
209*0fca6ea1SDimitry Andric bool hasStricterSpillThan(const RegSizeInfoByHwMode &I) const;
210*0fca6ea1SDimitry Andric
211*0fca6ea1SDimitry Andric void writeToStream(raw_ostream &OS) const;
212*0fca6ea1SDimitry Andric
insertRegSizeForModeRegSizeInfoByHwMode213*0fca6ea1SDimitry Andric void insertRegSizeForMode(unsigned Mode, RegSizeInfo Info) {
214*0fca6ea1SDimitry Andric Map.insert(std::pair(Mode, Info));
215*0fca6ea1SDimitry Andric }
216*0fca6ea1SDimitry Andric };
217*0fca6ea1SDimitry Andric
218*0fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T);
219*0fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T);
220*0fca6ea1SDimitry Andric
221*0fca6ea1SDimitry Andric struct SubRegRange {
222*0fca6ea1SDimitry Andric uint16_t Size;
223*0fca6ea1SDimitry Andric uint16_t Offset;
224*0fca6ea1SDimitry Andric
225*0fca6ea1SDimitry Andric SubRegRange(Record *R);
SubRegRangeSubRegRange226*0fca6ea1SDimitry Andric SubRegRange(uint16_t Size, uint16_t Offset) : Size(Size), Offset(Offset) {}
227*0fca6ea1SDimitry Andric };
228*0fca6ea1SDimitry Andric
229*0fca6ea1SDimitry Andric struct SubRegRangeByHwMode : public InfoByHwMode<SubRegRange> {
230*0fca6ea1SDimitry Andric SubRegRangeByHwMode(Record *R, const CodeGenHwModes &CGH);
SubRegRangeByHwModeSubRegRangeByHwMode231*0fca6ea1SDimitry Andric SubRegRangeByHwMode(SubRegRange Range) { Map.insert({DefaultMode, Range}); }
232*0fca6ea1SDimitry Andric SubRegRangeByHwMode() = default;
233*0fca6ea1SDimitry Andric
insertSubRegRangeForModeSubRegRangeByHwMode234*0fca6ea1SDimitry Andric void insertSubRegRangeForMode(unsigned Mode, SubRegRange Info) {
235*0fca6ea1SDimitry Andric Map.insert(std::pair(Mode, Info));
236*0fca6ea1SDimitry Andric }
237*0fca6ea1SDimitry Andric };
238*0fca6ea1SDimitry Andric
239*0fca6ea1SDimitry Andric struct EncodingInfoByHwMode : public InfoByHwMode<Record *> {
240*0fca6ea1SDimitry Andric EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH);
241*0fca6ea1SDimitry Andric EncodingInfoByHwMode() = default;
242*0fca6ea1SDimitry Andric };
243*0fca6ea1SDimitry Andric
244*0fca6ea1SDimitry Andric } // namespace llvm
245*0fca6ea1SDimitry Andric
246*0fca6ea1SDimitry Andric #endif // LLVM_UTILS_TABLEGEN_INFOBYHWMODE_H
247