1 | //===----------- ValueTypes.cpp - Implementation of EVT methods -----------===// |
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/CodeGen/ValueTypes.h" |
10 | #include "llvm/ADT/StringExtras.h" |
11 | #include "llvm/IR/DerivedTypes.h" |
12 | #include "llvm/IR/Type.h" |
13 | #include "llvm/Support/Debug.h" |
14 | #include "llvm/Support/ErrorHandling.h" |
15 | #include "llvm/Support/TypeSize.h" |
16 | #include "llvm/Support/WithColor.h" |
17 | using namespace llvm; |
18 | |
19 | EVT EVT::changeExtendedTypeToInteger() const { |
20 | assert(isExtended() && "Type is not extended!" ); |
21 | LLVMContext &Context = LLVMTy->getContext(); |
22 | return getIntegerVT(Context, BitWidth: getSizeInBits()); |
23 | } |
24 | |
25 | EVT EVT::changeExtendedVectorElementTypeToInteger() const { |
26 | assert(isExtended() && "Type is not extended!" ); |
27 | LLVMContext &Context = LLVMTy->getContext(); |
28 | EVT IntTy = getIntegerVT(Context, BitWidth: getScalarSizeInBits()); |
29 | return getVectorVT(Context, VT: IntTy, EC: getVectorElementCount()); |
30 | } |
31 | |
32 | EVT EVT::changeExtendedVectorElementType(EVT EltVT) const { |
33 | assert(isExtended() && "Type is not extended!" ); |
34 | LLVMContext &Context = LLVMTy->getContext(); |
35 | return getVectorVT(Context, VT: EltVT, EC: getVectorElementCount()); |
36 | } |
37 | |
38 | EVT EVT::getExtendedIntegerVT(LLVMContext &Context, unsigned BitWidth) { |
39 | EVT VT; |
40 | VT.LLVMTy = IntegerType::get(C&: Context, NumBits: BitWidth); |
41 | assert(VT.isExtended() && "Type is not extended!" ); |
42 | return VT; |
43 | } |
44 | |
45 | EVT EVT::getExtendedVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, |
46 | bool IsScalable) { |
47 | EVT ResultVT; |
48 | ResultVT.LLVMTy = |
49 | VectorType::get(ElementType: VT.getTypeForEVT(Context), NumElements, Scalable: IsScalable); |
50 | assert(ResultVT.isExtended() && "Type is not extended!" ); |
51 | return ResultVT; |
52 | } |
53 | |
54 | EVT EVT::getExtendedVectorVT(LLVMContext &Context, EVT VT, ElementCount EC) { |
55 | EVT ResultVT; |
56 | ResultVT.LLVMTy = VectorType::get(ElementType: VT.getTypeForEVT(Context), EC); |
57 | assert(ResultVT.isExtended() && "Type is not extended!" ); |
58 | return ResultVT; |
59 | } |
60 | |
61 | bool EVT::isExtendedFloatingPoint() const { |
62 | assert(isExtended() && "Type is not extended!" ); |
63 | return LLVMTy->isFPOrFPVectorTy(); |
64 | } |
65 | |
66 | bool EVT::isExtendedInteger() const { |
67 | assert(isExtended() && "Type is not extended!" ); |
68 | return LLVMTy->isIntOrIntVectorTy(); |
69 | } |
70 | |
71 | bool EVT::isExtendedScalarInteger() const { |
72 | assert(isExtended() && "Type is not extended!" ); |
73 | return LLVMTy->isIntegerTy(); |
74 | } |
75 | |
76 | bool EVT::isExtendedVector() const { |
77 | assert(isExtended() && "Type is not extended!" ); |
78 | return LLVMTy->isVectorTy(); |
79 | } |
80 | |
81 | bool EVT::isExtended16BitVector() const { |
82 | return isExtendedVector() && |
83 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 16); |
84 | } |
85 | |
86 | bool EVT::isExtended32BitVector() const { |
87 | return isExtendedVector() && |
88 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 32); |
89 | } |
90 | |
91 | bool EVT::isExtended64BitVector() const { |
92 | return isExtendedVector() && |
93 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 64); |
94 | } |
95 | |
96 | bool EVT::isExtended128BitVector() const { |
97 | return isExtendedVector() && |
98 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 128); |
99 | } |
100 | |
101 | bool EVT::isExtended256BitVector() const { |
102 | return isExtendedVector() && |
103 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 256); |
104 | } |
105 | |
106 | bool EVT::isExtended512BitVector() const { |
107 | return isExtendedVector() && |
108 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 512); |
109 | } |
110 | |
111 | bool EVT::isExtended1024BitVector() const { |
112 | return isExtendedVector() && |
113 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 1024); |
114 | } |
115 | |
116 | bool EVT::isExtended2048BitVector() const { |
117 | return isExtendedVector() && |
118 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 2048); |
119 | } |
120 | |
121 | bool EVT::isExtendedFixedLengthVector() const { |
122 | return isExtendedVector() && isa<FixedVectorType>(Val: LLVMTy); |
123 | } |
124 | |
125 | bool EVT::isExtendedScalableVector() const { |
126 | return isExtendedVector() && isa<ScalableVectorType>(Val: LLVMTy); |
127 | } |
128 | |
129 | EVT EVT::getExtendedVectorElementType() const { |
130 | assert(isExtended() && "Type is not extended!" ); |
131 | return EVT::getEVT(Ty: cast<VectorType>(Val: LLVMTy)->getElementType()); |
132 | } |
133 | |
134 | unsigned EVT::getExtendedVectorNumElements() const { |
135 | assert(isExtended() && "Type is not extended!" ); |
136 | ElementCount EC = cast<VectorType>(Val: LLVMTy)->getElementCount(); |
137 | if (EC.isScalable()) { |
138 | WithColor::warning() |
139 | << "The code that requested the fixed number of elements has made the " |
140 | "assumption that this vector is not scalable. This assumption was " |
141 | "not correct, and this may lead to broken code\n" ; |
142 | } |
143 | return EC.getKnownMinValue(); |
144 | } |
145 | |
146 | ElementCount EVT::getExtendedVectorElementCount() const { |
147 | assert(isExtended() && "Type is not extended!" ); |
148 | return cast<VectorType>(Val: LLVMTy)->getElementCount(); |
149 | } |
150 | |
151 | TypeSize EVT::getExtendedSizeInBits() const { |
152 | assert(isExtended() && "Type is not extended!" ); |
153 | if (IntegerType *ITy = dyn_cast<IntegerType>(Val: LLVMTy)) |
154 | return TypeSize::getFixed(ExactSize: ITy->getBitWidth()); |
155 | if (VectorType *VTy = dyn_cast<VectorType>(Val: LLVMTy)) |
156 | return VTy->getPrimitiveSizeInBits(); |
157 | llvm_unreachable("Unrecognized extended type!" ); |
158 | } |
159 | |
160 | /// getEVTString - This function returns value type as a string, e.g. "i32". |
161 | std::string EVT::getEVTString() const { |
162 | switch (V.SimpleTy) { |
163 | default: |
164 | if (isVector()) |
165 | return (isScalableVector() ? "nxv" : "v" ) + |
166 | utostr(X: getVectorElementCount().getKnownMinValue()) + |
167 | getVectorElementType().getEVTString(); |
168 | if (isInteger()) |
169 | return "i" + utostr(X: getSizeInBits()); |
170 | if (isFloatingPoint()) |
171 | return "f" + utostr(X: getSizeInBits()); |
172 | llvm_unreachable("Invalid EVT!" ); |
173 | case MVT::bf16: return "bf16" ; |
174 | case MVT::ppcf128: return "ppcf128" ; |
175 | case MVT::isVoid: return "isVoid" ; |
176 | case MVT::Other: return "ch" ; |
177 | case MVT::Glue: return "glue" ; |
178 | case MVT::x86mmx: return "x86mmx" ; |
179 | case MVT::x86amx: return "x86amx" ; |
180 | case MVT::i64x8: return "i64x8" ; |
181 | case MVT::Metadata: return "Metadata" ; |
182 | case MVT::Untyped: return "Untyped" ; |
183 | case MVT::funcref: return "funcref" ; |
184 | case MVT::exnref: return "exnref" ; |
185 | case MVT::externref: return "externref" ; |
186 | case MVT::aarch64svcount: |
187 | return "aarch64svcount" ; |
188 | case MVT::spirvbuiltin: |
189 | return "spirvbuiltin" ; |
190 | } |
191 | } |
192 | |
193 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
194 | void EVT::dump() const { |
195 | print(dbgs()); |
196 | dbgs() << "\n" ; |
197 | } |
198 | #endif |
199 | |
200 | /// getTypeForEVT - This method returns an LLVM type corresponding to the |
201 | /// specified EVT. For integer types, this returns an unsigned type. Note |
202 | /// that this will abort for types that cannot be represented. |
203 | Type *EVT::getTypeForEVT(LLVMContext &Context) const { |
204 | // clang-format off |
205 | switch (V.SimpleTy) { |
206 | default: |
207 | assert(isExtended() && "Type is not extended!" ); |
208 | return LLVMTy; |
209 | case MVT::isVoid: return Type::getVoidTy(C&: Context); |
210 | case MVT::x86mmx: return Type::getX86_MMXTy(C&: Context); |
211 | case MVT::aarch64svcount: |
212 | return TargetExtType::get(Context, Name: "aarch64.svcount" ); |
213 | case MVT::x86amx: return Type::getX86_AMXTy(C&: Context); |
214 | case MVT::i64x8: return IntegerType::get(C&: Context, NumBits: 512); |
215 | case MVT::externref: return Type::getWasm_ExternrefTy(C&: Context); |
216 | case MVT::funcref: return Type::getWasm_FuncrefTy(C&: Context); |
217 | case MVT::Metadata: return Type::getMetadataTy(C&: Context); |
218 | #define GET_VT_EVT(Ty, EVT) case MVT::Ty: return EVT; |
219 | #include "llvm/CodeGen/GenVT.inc" |
220 | #undef GET_VT_EVT |
221 | } |
222 | // clang-format on |
223 | } |
224 | |
225 | /// Return the value type corresponding to the specified type. |
226 | /// If HandleUnknown is true, unknown types are returned as Other, otherwise |
227 | /// they are invalid. |
228 | /// NB: This includes pointer types, which require a DataLayout to convert |
229 | /// to a concrete value type. |
230 | MVT MVT::getVT(Type *Ty, bool HandleUnknown){ |
231 | assert(Ty != nullptr && "Invalid type" ); |
232 | switch (Ty->getTypeID()) { |
233 | default: |
234 | if (HandleUnknown) return MVT(MVT::Other); |
235 | llvm_unreachable("Unknown type!" ); |
236 | case Type::VoidTyID: |
237 | return MVT::isVoid; |
238 | case Type::IntegerTyID: |
239 | return getIntegerVT(BitWidth: cast<IntegerType>(Val: Ty)->getBitWidth()); |
240 | case Type::HalfTyID: return MVT(MVT::f16); |
241 | case Type::BFloatTyID: return MVT(MVT::bf16); |
242 | case Type::FloatTyID: return MVT(MVT::f32); |
243 | case Type::DoubleTyID: return MVT(MVT::f64); |
244 | case Type::X86_FP80TyID: return MVT(MVT::f80); |
245 | case Type::X86_MMXTyID: return MVT(MVT::x86mmx); |
246 | case Type::TargetExtTyID: { |
247 | TargetExtType *TargetExtTy = cast<TargetExtType>(Val: Ty); |
248 | if (TargetExtTy->getName() == "aarch64.svcount" ) |
249 | return MVT(MVT::aarch64svcount); |
250 | else if (TargetExtTy->getName().starts_with(Prefix: "spirv." )) |
251 | return MVT(MVT::spirvbuiltin); |
252 | if (HandleUnknown) |
253 | return MVT(MVT::Other); |
254 | llvm_unreachable("Unknown target ext type!" ); |
255 | } |
256 | case Type::X86_AMXTyID: return MVT(MVT::x86amx); |
257 | case Type::FP128TyID: return MVT(MVT::f128); |
258 | case Type::PPC_FP128TyID: return MVT(MVT::ppcf128); |
259 | case Type::FixedVectorTyID: |
260 | case Type::ScalableVectorTyID: { |
261 | VectorType *VTy = cast<VectorType>(Val: Ty); |
262 | return getVectorVT( |
263 | VT: getVT(Ty: VTy->getElementType(), /*HandleUnknown=*/ false), |
264 | EC: VTy->getElementCount()); |
265 | } |
266 | } |
267 | } |
268 | |
269 | /// getEVT - Return the value type corresponding to the specified type. |
270 | /// If HandleUnknown is true, unknown types are returned as Other, otherwise |
271 | /// they are invalid. |
272 | /// NB: This includes pointer types, which require a DataLayout to convert |
273 | /// to a concrete value type. |
274 | EVT EVT::getEVT(Type *Ty, bool HandleUnknown){ |
275 | switch (Ty->getTypeID()) { |
276 | default: |
277 | return MVT::getVT(Ty, HandleUnknown); |
278 | case Type::TokenTyID: |
279 | return MVT::Untyped; |
280 | case Type::IntegerTyID: |
281 | return getIntegerVT(Context&: Ty->getContext(), BitWidth: cast<IntegerType>(Val: Ty)->getBitWidth()); |
282 | case Type::FixedVectorTyID: |
283 | case Type::ScalableVectorTyID: { |
284 | VectorType *VTy = cast<VectorType>(Val: Ty); |
285 | return getVectorVT(Context&: Ty->getContext(), |
286 | VT: getEVT(Ty: VTy->getElementType(), /*HandleUnknown=*/ false), |
287 | EC: VTy->getElementCount()); |
288 | } |
289 | } |
290 | } |
291 | |
292 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
293 | void MVT::dump() const { |
294 | print(dbgs()); |
295 | dbgs() << "\n" ; |
296 | } |
297 | #endif |
298 | |
299 | void MVT::print(raw_ostream &OS) const { |
300 | if (SimpleTy == INVALID_SIMPLE_VALUE_TYPE) |
301 | OS << "invalid" ; |
302 | else |
303 | OS << EVT(*this).getEVTString(); |
304 | } |
305 | |
306 | |