xref: /llvm-project/llvm/utils/TableGen/Basic/VTEmitter.cpp (revision 1714facf4f7d7f4ef5a1846aded769fec8e684ac)
1 //===- VTEmitter.cpp - Generate properties from ValueTypes.td -------------===//
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 
9 #include "llvm/ADT/StringRef.h"
10 #include "llvm/Support/raw_ostream.h"
11 #include "llvm/TableGen/Record.h"
12 #include "llvm/TableGen/TableGenBackend.h"
13 #include <cassert>
14 #include <map>
15 using namespace llvm;
16 
17 namespace {
18 
19 class VTEmitter {
20 private:
21   const RecordKeeper &Records;
22 
23 public:
24   VTEmitter(const RecordKeeper &R) : Records(R) {}
25 
26   void run(raw_ostream &OS);
27 };
28 
29 } // End anonymous namespace.
30 
31 static void vTtoGetLlvmTyString(raw_ostream &OS, const Record *VT) {
32   bool IsVector = VT->getValueAsBit("isVector");
33   bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple");
34 
35   if (IsRISCVVecTuple) {
36     unsigned NElem = VT->getValueAsInt("nElem");
37     unsigned Sz = VT->getValueAsInt("Size");
38     OS << "TargetExtType::get(Context, \"riscv.vector.tuple\", "
39           "ScalableVectorType::get(Type::getInt8Ty(Context), "
40        << (Sz / (NElem * 8)) << "), " << NElem << ")";
41     return;
42   }
43 
44   if (IsVector)
45     OS << (VT->getValueAsBit("isScalable") ? "Scalable" : "Fixed")
46        << "VectorType::get(";
47 
48   auto OutputVT = IsVector ? VT->getValueAsDef("ElementType") : VT;
49   int64_t OutputVTSize = OutputVT->getValueAsInt("Size");
50 
51   if (OutputVT->getValueAsBit("isFP")) {
52     StringRef FloatTy;
53     auto OutputVTName = OutputVT->getValueAsString("LLVMName");
54     switch (OutputVTSize) {
55     default:
56       llvm_unreachable("Unhandled case");
57     case 16:
58       FloatTy = (OutputVTName == "bf16") ? "BFloatTy" : "HalfTy";
59       break;
60     case 32:
61       FloatTy = "FloatTy";
62       break;
63     case 64:
64       FloatTy = "DoubleTy";
65       break;
66     case 80:
67       FloatTy = "X86_FP80Ty";
68       break;
69     case 128:
70       FloatTy = (OutputVTName == "ppcf128") ? "PPC_FP128Ty" : "FP128Ty";
71       break;
72     }
73     OS << "Type::get" << FloatTy << "(Context)";
74   } else if (OutputVT->getValueAsBit("isInteger")) {
75     // We only have Type::getInt1Ty, Int8, Int16, Int32, Int64, and Int128
76     if ((isPowerOf2_64(OutputVTSize) && OutputVTSize >= 8 &&
77          OutputVTSize <= 128) ||
78         OutputVTSize == 1)
79       OS << "Type::getInt" << OutputVTSize << "Ty(Context)";
80     else
81       OS << "Type::getIntNTy(Context, " << OutputVTSize << ")";
82   } else
83     llvm_unreachable("Unhandled case");
84 
85   if (IsVector)
86     OS << ", " << VT->getValueAsInt("nElem") << ")";
87 }
88 
89 void VTEmitter::run(raw_ostream &OS) {
90   emitSourceFileHeader("ValueTypes Source Fragment", OS, Records);
91 
92   std::vector<const Record *> VTsByNumber{512};
93   for (auto *VT : Records.getAllDerivedDefinitions("ValueType")) {
94     auto Number = VT->getValueAsInt("Value");
95     assert(0 <= Number && Number < (int)VTsByNumber.size() &&
96            "ValueType should be uint16_t");
97     assert(!VTsByNumber[Number] && "Duplicate ValueType");
98     VTsByNumber[Number] = VT;
99   }
100 
101   struct VTRange {
102     StringRef First;
103     StringRef Last;
104     bool Closed;
105   };
106 
107   std::map<StringRef, VTRange> VTRanges;
108 
109   auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name,
110                                    bool Valid) {
111     if (Valid) {
112       auto [It, Inserted] = VTRanges.try_emplace(Key);
113       if (Inserted)
114         It->second.First = Name;
115       assert(!It->second.Closed && "Gap detected!");
116       It->second.Last = Name;
117     } else if (auto It = VTRanges.find(Key); It != VTRanges.end()) {
118       It->second.Closed = true;
119     }
120   };
121 
122   OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc, Tup, NF, "
123         "NElem, EltTy)\n";
124   for (const auto *VT : VTsByNumber) {
125     if (!VT)
126       continue;
127     auto Name = VT->getValueAsString("LLVMName");
128     auto Value = VT->getValueAsInt("Value");
129     bool IsInteger = VT->getValueAsBit("isInteger");
130     bool IsFP = VT->getValueAsBit("isFP");
131     bool IsVector = VT->getValueAsBit("isVector");
132     bool IsScalable = VT->getValueAsBit("isScalable");
133     bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple");
134     int64_t NF = VT->getValueAsInt("NF");
135     bool IsNormalValueType =  VT->getValueAsBit("isNormalValueType");
136     int64_t NElem = IsVector ? VT->getValueAsInt("nElem") : 0;
137     StringRef EltName = IsVector ? VT->getValueAsDef("ElementType")->getName()
138                                  : "INVALID_SIMPLE_VALUE_TYPE";
139 
140     UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name,
141                   IsInteger && IsVector && !IsScalable);
142     UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name,
143                   IsInteger && IsScalable);
144     UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name,
145                   IsFP && IsVector && !IsScalable);
146     UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable);
147     UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable);
148     UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable);
149     UpdateVTRange("RISCV_VECTOR_TUPLE_VALUETYPE", Name, IsRISCVVecTuple);
150     UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector);
151     UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector);
152     UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector);
153     UpdateVTRange("VALUETYPE", Name, IsNormalValueType);
154 
155     // clang-format off
156     OS << "  GET_VT_ATTR("
157        << Name << ", "
158        << Value << ", "
159        << VT->getValueAsInt("Size") << ", "
160        << VT->getValueAsBit("isOverloaded") << ", "
161        << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", "
162        << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", "
163        << IsVector << ", "
164        << IsScalable << ", "
165        << IsRISCVVecTuple << ", "
166        << NF << ", "
167        << NElem << ", "
168        << EltName << ")\n";
169     // clang-format on
170   }
171   OS << "#endif\n\n";
172 
173   OS << "#ifdef GET_VT_RANGES\n";
174   for (const auto &KV : VTRanges) {
175     assert(KV.second.Closed);
176     OS << "  FIRST_" << KV.first << " = " << KV.second.First << ",\n"
177        << "  LAST_" << KV.first << " = " << KV.second.Last << ",\n";
178   }
179   OS << "#endif\n\n";
180 
181   OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, Tup, nElem, ElTy)\n";
182   for (const auto *VT : VTsByNumber) {
183     if (!VT || !VT->getValueAsBit("isVector"))
184       continue;
185     const auto *ElTy = VT->getValueAsDef("ElementType");
186     assert(ElTy);
187     // clang-format off
188     OS << "  GET_VT_VECATTR("
189        << VT->getValueAsString("LLVMName") << ", "
190        << VT->getValueAsBit("isScalable") << ", "
191        << VT->getValueAsBit("isRISCVVecTuple") << ", "
192        << VT->getValueAsInt("nElem") << ", "
193        << ElTy->getName() << ")\n";
194     // clang-format on
195   }
196   OS << "#endif\n\n";
197 
198   OS << "#ifdef GET_VT_EVT\n";
199   for (const auto *VT : VTsByNumber) {
200     if (!VT)
201       continue;
202     bool IsInteger = VT->getValueAsBit("isInteger");
203     bool IsVector = VT->getValueAsBit("isVector");
204     bool IsFP = VT->getValueAsBit("isFP");
205     bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple");
206 
207     if (!IsInteger && !IsVector && !IsFP && !IsRISCVVecTuple)
208       continue;
209 
210     OS << "  GET_VT_EVT(" << VT->getValueAsString("LLVMName") << ", ";
211     vTtoGetLlvmTyString(OS, VT);
212     OS << ")\n";
213   }
214   OS << "#endif\n\n";
215 }
216 
217 static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType");
218