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